3

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

做这样的事情时,我是否必须处理虚假唤醒:

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需要易变还是没有必要?

4

1 回答 1

2

事件(MRE、ARE 和精简版本)没有虚假唤醒。如果这些对象存在这种情况,几乎所有 Windows 程序都会崩溃。你在和风车搏斗。但是,是的,包括等待和设置事件在内的许多同步功能都会执行完整的内存屏障(这很好理解,但没有记录在案)。允许虚假唤醒的条件变量(如文档所述)。它们与事件无关。

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

文档说:

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

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

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

于 2015-05-13T19:52:55.293 回答