是否每次调用SetEvent for autoreset事件都会唤醒一个线程?

时间:2012-12-04 12:23:40

标签: multithreading winapi synchronization

有三个线程和autoreset事件。 当第二个和第三个线程正在等待此事件时,第一个线程调用SetEvent两次。 系统是否保证两个等待线程都会被唤醒?

我在MSDN中读到了.NET Framework AutoResetEvent类的这个注释: 无法保证每次调用Set方法都会释放一个线程。如果两个调用太靠近,那么第二次调用在线程释放之前发生,则只释放一个线程。就好像第二次通话没有发生一样。

Win32 API是否正确?

1 个答案:

答案 0 :(得分:2)

请考虑以下情况:

Event Signaled | Thread 1   | Thread 2      | Thread 3
---------------------------------------------------------
false          | SetEvent() |               |            
true           |            |               |            
true           |            | Wait Complete |            
false          |            |               |            
false          | SetEvent() |               |            
true           |            |               |            
true           |            |               | Wait Complete
false          |            |               |            

成功

Event Signaled | Thread 1   | Thread 2      | Thread 3
---------------------------------------------------------
false          | SetEvent() |               |            
true           |            |               |  
true           | SetEvent() |               |            
true           |            |               |            
true           |            | Wait Complete |            
false          |            |               |            
false          |            |               | Wait does not complete
false          |            |               |    

失败

根据在特定时间执行哪个线程,您可能会也可能不会完成其他线程上的等待。

您应该将事件更改为手动重置事件,以确保所有线程都能完成等待,并在需要时使用ResetEvent将事件设置回无信号。

还有其他选项,例如使用semaphore来控制访问权限,或者critical section如果您只计划等待很短的时间(自旋锁定性能),而是手动重置事件似乎是要走的路。一般情况下,请查看synchronization objects