注意:我受限于.NET 3.5,因此我无法使用ManualResetEventSlim
。EventWaitHandle是否必须处理虚假唤醒?
我必须做这样的事情的时候,处理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
需要是易失性还是不必要?
没有虚假唤醒。如果有这样的事情,几乎所有的Windows程序都会中断。你在与风车搏斗。但是,是的,同步功能执行完整的内存屏障(这是很好理解,但没有记录)。 – usr
我不同意:https://msdn.microsoft.com/en-us/library/windows/desktop/ms682052%28v=vs.85%29.aspx“条件变量受到虚假唤醒的影响(那些不相关的并且唤醒被唤醒(另一个线程在唤醒线程之前运行)因此,在睡眠操作返回之后,您应该重新检查谓词(通常在while循环中)。“ 也在.NET 4.0+中有这样的代码:http://referencesource.microsoft.com/#mscorlib/system/threading/ManualResetEventSlim.cs,635“//应对来自其他正在取消等待的虚假唤醒的循环“ –
事件不是一个条件变量。这不适用。源代码告诉你,框架为你处理这种情况。虚假唤醒不会暴露给用户代码。它们是您在那里挖掘的实现细节。 – usr