zoukankan      html  css  js  c++  java
  • AutoResetEvent实现并发同步

    AutoResetEvent,继承自EventWaitHandle,用在多线程中保护对共享资源的访问,保证每次只能有一个线程对共享资源进行访问

    AutoResetEvent最特别之处,在于每次保证只有一个线程执行逻辑,其他的线程只能等待。

    AutoResetEvent通过信号量来阻塞和释放线程。其基本原理如下:

    1、如果AutoResetEvent在无信号状态时,执行了WaitOne()方法之后,当前线程就会被阻塞,直到该AutoResetEvent在其他地方执行了Set()方法后,此时AutoResetEvent就获得了信号并释放一个线程,然后自动执行Reset()方法(即失去信号)。

    如果当AutoResetEvent执行Set()方法后,没有等待任何等待的线程,则该AutoResetEvent会一直保持持有信号;

    2、如果AutoResetEvent在有信号时,执行了WaitOne方法,当前线程会被立即释放,并且AutoResetEvent也会失去信号。

    代码如下所示:

            
    static AutoResetEvent autoResetEvent=new AutoResetEvent(true);
    static void WorkOnAutoResetEvent(string threadName) { Console.WriteLine($"{threadName} 正在等待中..."); autoResetEvent.WaitOne(); Console.WriteLine($"{threadName} 执行中..."); Thread.Sleep(1000); Console.WriteLine($"{threadName} 执行完毕!"); //得到信号,并释放一个被阻塞的线程,然后丢失信号(即自动执行Reset()方法);如果没有线程可以被释放,则它会一直保持信号 autoResetEvent.Set(); }

    Main中代码如下所示:

                for (int i = 0; i < 3; i++) {
                    string threadName = $"thread_{i}";
                    var thread = new Thread(delegate ()
                      {
                          WorkOnAutoResetEvent(threadName);
                      });
                    thread.Start();
                }

    结果:

      

    为何AutoResetEvent会被以Auto开始的单词命名,因为它在得到信号并释放一个被阻塞的线程之后,会自动的执行Reset()方法,即自动丢失信号,这就是它的自动之处。

    当然,如果它在得到信号,但此时并没有任何阻塞的线程被释放,它就会一直保持持有信号,直到下一个WaitOne()方法被执行。

    在调用Set()方法之后,它就获得了信号,如果释放了一个阻塞的线程,它会自动执行Reset()丢失信号;如果没有释放线程,则它不会丢失信号。这是关键之处!

    参考文献:https://docs.microsoft.com/en-us/dotnet/api/system.threading.autoresetevent?view=netcore-3.1#explicit-interface-implementations

  • 相关阅读:
    ClouderaManager与CDH
    教辅的组成
    国家集训队 小Z的袜子
    国家集训队 旅游
    NOIP2015 子串
    数颜色
    间谍网络
    NOIP2017 逛公园
    APIO2009 抢掠计划
    JLOI2014 松鼠的新家
  • 原文地址:https://www.cnblogs.com/williamwsj/p/13853395.html
Copyright © 2011-2022 走看看