zoukankan      html  css  js  c++  java
  • 线程同步之-旋转门AutoResetEvent(好像旋转自动门一样,一边打开,另一边关闭)

      主要作用:从一个线程向另一个线程发送通知,进行线程同步。

      有点像旋转门,一次只允许一个人通过(一边等待,一边通过,如此循环)

      AutoResetEvent 常常被用来在两个线程之间进行信号发送,两个线程共享相同的AutoResetEvent对象,线程可以通过调用AutoResetEvent对象的WaitOne()方法进入等待状态,然后另外一个线程通过调用AutoResetEvent对象的Set()方法取消等待的状态。

      使用场景:几个线程之间相互交替,或者以某种顺序完成任务时。

    参考资源:https://www.cnblogs.com/czytcn/p/8085071.html

         static void Main(string[] args)
            {
                var t = new Thread(() => Process(10));
                t.Start();
    
                Console.WriteLine("进程开始,主线程.等待另一个线程完成工作(主线程)......");
                
                _workerEvent.WaitOne();//阻止当前线程(主线程到这里阻塞),等子线程(其他任务持有_workerEvent对象的线程)的通知【任务线程调用这个对象的WaitOne都会被阻塞】
    
                //收到子线程通知,继续执行
                Console.WriteLine("收到子线程完成任务通知了111(主线程)!");
                Thread.Sleep(5000);
                Console.WriteLine("我主线程干活111(主线程)...");
                Thread.Sleep(TimeSpan.FromSeconds(5));
                Console.WriteLine("我主线程干完活了...通知子线程666(主线程)");
                Thread.Sleep(3000);
                _mainEvent.Set();
                
                //Console.WriteLine("Now running the second operation on a second thread");
                
                _workerEvent.WaitOne();//等待子线程
    
                Console.WriteLine("主线程收到通知888,并最终完成(主线程)!");
                Console.Read();
            }
    
            private static AutoResetEvent _workerEvent = new AutoResetEvent(false);//交警1
            private static AutoResetEvent _mainEvent = new AutoResetEvent(false);//交警2
    
            static void Process(int seconds)
            {
                Thread.Sleep(3000);
                //主线程等待时执行的操作
                Console.WriteLine("子线程开始工作(子线程)...");
                Thread.Sleep(TimeSpan.FromSeconds(seconds));
                Console.WriteLine("子线程工作中(子线程)...");
                Thread.Sleep(10000);
                Console.WriteLine("子线程工作完成!并通知主线程开始干活111(子线程)...");
    
                _workerEvent.Set();//通知主线程可以干活
                
                //Console.WriteLine("子线程开始等待主线程...");
                
                _mainEvent.WaitOne();//等待主线程
    
                Console.WriteLine("收到主线程通知666,我开干了(子线程)...");
                Thread.Sleep(TimeSpan.FromSeconds(seconds));
                Console.WriteLine("子线程工作完成!通知主线程888(子线程)");
                Thread.Sleep(5000);
                _workerEvent.Set();//通知主线程开始干活
            }

      ManualResetEventSlim的整个工作方法有点像人群通过大门,AutoResetEvent事件像一个旋转门,一次只允许一人通过。ManualResetEventSlim是ManualResetEvent的混合版本,一直保持大门敞开直到手动调用Reset方法。当调用_mainEvent.Set时,相当于打开了大门从而允许准备好的线程接收信号并继续工作。然而线程3还处于睡眠状态,没有赶上时间。当调用_mainEvent.Reset相当于关闭了大门。最后一个线程已经准备好要执行,但是不得不等待下一个信号。

  • 相关阅读:
    PHP面向对象之原型(trait)
    PHP面向对象之命名空间
    Javascript中的Copy()函数
    六、unique_lock取代lock_guard
    五、互斥量
    四、创建和等待多个线程
    三、线程传参
    二、线程的启动与结束 join与detach
    HTTP:常见状态码
    HTTP:简述URL、URN和URI
  • 原文地址:https://www.cnblogs.com/gougou1981/p/12344075.html
Copyright © 2011-2022 走看看