注意:我仅限于.NET 3.5,所以不能使用ManualResetEventSlim

做这样的事情时,我是否必须处理Spurious wakeups

var waitHandle = new EventWaitHandle();
new Thread(() =>
{
    Thread.Sleep(TimeSpan.FromSeconds(5));
    waitHandler.Set();
});
waitHandle.WaitOne();


如果是这样,则在调用Set和/或WaitOne时是否设置了正确的内存屏障,以确保安全:

var reallyDone = false;
var waitHandle = new EventWaitHandle();
new Thread(() =>
{
    Thread.Sleep(TimeSpan.FromSeconds(5));
    reallyDone = true;
    waitHandler.Set();
});
while (!reallyDone)
    waitHandle.WaitOne();


特别是,由于指令重新排序或缓存,本示例中的主线程是否可能看不到reallyDone设置为true?在这种情况下,reallyDone是否需要保持易失性?

最佳答案

没有虚假的事件唤醒(MRE,ARE和苗条版本)。如果这些对象发生这种事情,几乎所有Windows程序都会中断。你在打风车。但是是的,许多同步功能(包括等待事件和设置事件)执行完整的内存屏障(众所周知,但未在任何地方记载)。条件变量以允许虚假唤醒(如docs所述)。它们与事件无关。

另外,为什么会有虚假的唤醒?从API的角度来看没有任何意义。该事件可能会在内部循环并向您隐藏虚假的唤醒(实际上,MRESlim会这样做)。我只能重复一遍:几乎所有程序都会中断。那不是现实。

The docs say:


  阻塞当前线程,直到当前的WaitHandle接收到信号为止。
  此方法的调用者无限期地阻塞,直到当前实例接收到信号为止。


如果在事件的上下文中存在虚假唤醒,则这些陈述将为假。

您误解了所见。您有一个错误,但不是由事件引起的。不需要reallyDone技术。

关于c# - EventWaitHandle是否必须处理虚假唤醒?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30223042/

10-09 00:22