AutoResetEvent实现单并发控制

AutoResetEvent是EventWaitHandle的一个简单包装,内部没有额外的任何逻辑。它最大的特点就是,调用了Set方法将事件设为true之后,其中一个等待线程得到执行后,它会自动调用Reset方法,将事件信号设为false,以阻塞其它的线程。相当于放一个线程进来,门自动就关了(自动门)

例子,使用AutoResetEvent实现一个简单的线程同步锁。

 1  private class SimpleWaitLock : IDisposable
 2         {
 3             //初始化一定要是true,否则,第一个调用Enter方法的线程会被阻塞
 4             private AutoResetEvent m_autoResetEvent = new AutoResetEvent(true);
 5             
 6             
 7             public void Enter()
 8             {
 9                 //第一个线程调用这个方法后,事件将会为false,其他线程会被阻塞
10                 m_autoResetEvent.WaitOne();                
11                 Console.WriteLine("Thread {0} Enter;",Thread.CurrentThread.Name);
12                 Thread.Sleep(100);
13                 Exit();
14             }
15             public void Exit()
16             {
17                 Console.WriteLine("Thread {0} Exit;", Thread.CurrentThread.Name);
18                 m_autoResetEvent.Set();
19                 
20             }
21             public void Dispose()
22             {
23                 m_autoResetEvent.Dispose();
24                 Console.WriteLine("Thread {0} dispose;", Thread.CurrentThread.Name);
25             }
26         }
27         static void Main()
28         {
29             SimpleWaitLock slock = new SimpleWaitLock();
30             for (int i = 0; i < 10; i++)
31             {
32                 Thread thread = new Thread(slock.Enter);
33                 thread.Name = "thread" + i.ToString();
34                 thread.Start();                
35             }
36             Console.Read();
37         }
38      
39 
40     }

执行结果:

ManualResetEvent

ManualResetEvent是EventWaitHandle的一个简单包装,内部也没有额外的任何逻辑。它和AutoResetEvent唯一的不同是,调用了Set方法将事件设为true后,不会去调用Reset方法,这将导致事件一直处于true,其它等待的多个线程都会得到执行,直到你手动调用Reset方法。相当于你把门打开后,需要手动去关(非自动门)

View Code
 1  private class SimpleWaitLock : IDisposable
 2         {
 3             //初始化一定要是true,否则,第一个调用Enter方法的线程会被阻塞
 4             private ManualResetEvent m_mannualResetEvent = new ManualResetEvent(false);
 5             
 6             
 7             public void Enter()
 8             {
 9                 //第一个线程调用这个方法后,事件将会为false,其他线程会被阻塞                
10                 m_mannualResetEvent.WaitOne();                
11                 Console.WriteLine("Thread {0} Enter;",Thread.CurrentThread.Name);
12                 Thread.Sleep(100);
13                 
14             }
15             public void Exit()
16             {
17                 //Console.WriteLine("Thread {0} Exit;", Thread.CurrentThread.Name);
18                 m_mannualResetEvent.Set();          
19                 
20             }
21             public void Dispose()
22             {
23                 m_mannualResetEvent.Dispose();
24                 Console.WriteLine("Thread {0} dispose;", Thread.CurrentThread.Name);
25             }
26         }
27         static void Main()
28         {
29             SimpleWaitLock slock = new SimpleWaitLock();
30             for (int i = 0; i < 10; i++)
31             {
32                 Thread thread = new Thread(slock.Enter);
33                 thread.Name = "thread" + i.ToString();
34                 thread.Start();                
35             }
36             Thread.Sleep(1000);
37             Console.WriteLine("The door is open, all threads can go over...");
38             slock.Exit();
39             Console.Read();
40         }
41      
42 
43     }

执行结果如下:

总结:

1、看起来,ManualResetEvent更加自由、开放。如果把AutoResetEvent看作是只能单人通过的独木桥的话,那么ManualResetEvent就像一座城门,一下子可以涌入千军万马,当然你也可以随时关闭城门,让后面的人进不来。

2、AutoResetEvent.Set() = ManualResetEvent.Set() + ManualResetEvent.Reset();

3、如果共享资源仅允许一个线程单独使用的情况下,可以选择AutoResetEvent;如果共享资源允许多个线程同时使用,则可以选择ManualResetEvent

4、如果要控制多个线程暂停、继续,可以选择ManualResetEvent

5。而Semaphore可实现多并发同步控制

原文地址:https://www.cnblogs.com/Finding2013/p/3012616.html