目前,我正在学习多线程考试。我看了the good threading article of albahari。我对显示器的用法有疑问 - 为什么这里使用了一个循环代替if?
lock (_locker)
{
while (!_go) //why while and not if?
Monitor.Wait (_locker); // _lock is released
// lock is regained
...
}
我认为,if就足够了。
我很害怕,我完全不理解这篇文章。
//编辑 实施例-代码:
class SimpleWaitPulse
{
static readonly object _locker = new object();
static bool _go;
static void Main()
{ // The new thread will block
new Thread (Work).Start(); // because _go==false.
Console.ReadLine(); // Wait for user to hit Enter
lock (_locker) // Let's now wake up the thread by
{ // setting _go=true and pulsing.
_go = true;
Monitor.Pulse (_locker);
}
}
static void Work()
{
lock (_locker)
while (!_go)
Monitor.Wait (_locker); // Lock is released while we’re waiting
Console.WriteLine ("Woken!!!");
}
}
答案 0 :(得分:5)
这取决于具体情况。在这种情况下,代码只是等待_go
true 。
每次_locker
发出脉冲时,都会检查_go
是否已设置为 true 。如果_go
仍为 false ,则会等待下一个脉冲。
如果使用 if 而不是而,它只会等待一次(如果_go
已经为真,则根本不会等待< / strong>),然后在脉冲后继续,无论_go
的新状态如何。
所以你如何使用Monitor.Wait()完全取决于你的具体需求。
答案 1 :(得分:3)
这实际上取决于具体情况。但首先,我们需要澄清监视器的工作原理。当一个线程继续通过Monitor.Pulse()发出一个线程信号时,通常无法保证发出信号的线程实际上会在下一次运行。这意味着其他线程可以在发出信号的线程之前运行,并更改信号线程可以继续运行的条件。这意味着发出信号的线程仍然需要检查在被唤醒后是否安全(即while循环)。但是,某些罕见的同步问题允许您假设一旦线程被发出信号唤醒(即Monitor.Pulse()),其他任何线程都无法改变其安全进行的条件(即。如果条件)。
答案 2 :(得分:2)
我写了一篇可能对此有所帮助的文章:Wait and Pulse demystified
还有更多事情发生,而且很明显。
答案 3 :(得分:1)
我对显示器的用法有疑问 - 为什么这里使用了循环 一个if的地方?
使用Pulse
和Wait
时,有一个众所周知的规则,即当有疑问时,while
更喜欢if
。显然,任何一个都可以在这种情况下工作,但在几乎所有其他情况下都需要while
。事实上,使用while
循环的情况很少(如果有)会产生不正确的结果。这是这个一般规则的基础。作者使用了while
循环,因为他试图坚持使用经过验证的模式。他甚至在同一篇文章中提供了模板。这是:
lock (_locker)
while ( <blocking-condition> )
Monitor.Wait (_locker);
答案 4 :(得分:0)
使用Monitor.Wait
编写正确代码的最简单方法是假设系统将其视为“建议”,并假设系统可以在任何时候获取锁定时任意唤醒任何等待线程,而不考虑是否已调用Pulse
。当然,系统通常不会这样做,但如果某个程序正确使用Wait
和Pulse
,则{{1}不应影响其正确性}无条件地提前任意退出。从本质上讲,应该将Wait
视为告诉系统的一种方式“除非或直到其他人打电话给Wait
”,否则继续执行此处将是浪费时间。