剧透注:问题是最后一句话。
在 C# 中,使用条件变量的经典模式是这样的:
lock (answersQueue)
{
answersQueue.Enqueue(c);
Monitor.Pulse(answersQueue); // condition variable "notify one".
}
和其他一些线程:
lock (answersQueue)
{
while (answersQueue.Count == 0)
{
// unlock answer queue and sleeps here until notified.
Monitor.Wait(answersQueue);
}
...
}
这是我的代码中的一个例子。如果我将 Pulse 放在锁定范围之外,它不会编译。但是,这是正确的方法:cf:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686903(v=vs.85).aspx 和: http: //www.installsetupconfig.com/win32programming/threadprocesssynchronizationapis11_7.html (搜索“里面”)
实际上,当您仍处于关键部分时,向睡眠线程发出信号是愚蠢的。因为睡眠线程不能唤醒(不是立即),因为它也在一个关键部分中!
因此,我希望 .NET 或 C# Pulse 调用实际上只是标记锁定对象,以便当它超出范围时,此时它实际上“脉冲”条件变量。因为否则,它将有一个最优性问题。
那么,Monitor 对象的设计是如何选择的呢?
编辑:
我在这篇论文中找到了答案: http ://research.microsoft.com/pubs/64242/implementingcvs.pdf 部分“优化信号和广播”以及上一节关于 NT 内核以及如何在信号量之上制作条件变量,这就是引入“该死的队列”的原因。现在,这让我成为了一名更好的工程师。