EventWaitHandle是否必须处理虚假的尾流?

时间:2015-05-13 18:51:58

标签: c# .net .net-3.5 waithandle

注意:我受限于.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是否需要易变?或者这是不必要的?

1 个答案:

答案 0 :(得分:2)

事件(MRE,ARE和超薄版本)没有虚假的唤醒。如果这些对象有这样的东西,几乎所有的Windows程序都会破坏。你在和风车作战。但是,许多同步功能(包括等待和设置事件)执行完整的内存屏障(这是很好理解但未记录)。条件变量允许虚假唤醒(如文档所述)。它们与事件无关。

另外,为什么会有虚假的唤醒?从API的角度来看没有意义。事件可以在内部循环并隐藏你的虚假唤醒(事实上,MRESlim会这样做)。我只能重复一遍:几乎所有的节目都会破裂。那不是现实。

The docs say:

  

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

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

你误解了你所看到的。你有一个错误,但它不是由事件引起的。 <{1}}技术不是必需的。