2012-01-16 43 views
5

目前,我正在学习多线程考试。我读the good threading article of albahari。我在监视器使用中遇到了一个问题 - 为什么在这里使用循环代替if?Monitor.Wait - while or if?

lock (_locker) 
{ 
    while (!_go) //why while and not if? 
    Monitor.Wait (_locker); // _lock is released 
    // lock is regained 
    ... 
} 

我认为,如果将是足够的。

恐怕,我完全不理解这篇文章。

//编辑 例码:

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!!!"); 
    } 
} 
+1

“If”只检查一次。 “while”循环将继续检查。如果不等。等待。 – DOK 2012-01-16 19:14:21

+0

Hi DOK - 感谢您的解释。但是我认为,Monitor.Wait操作只会执行一次。它将等待脉冲信号。所以我没有看到一段时间的理由:-( – bitsmuggler 2012-01-16 19:18:16

+0

它取决于程序的其余部分,像'_go'究竟是什么意思,你什么时候设置它 – svick 2012-01-16 19:21:39

回答

5

它只是视情况而定。在这种情况下,代码只是等待_gotrue

每次_locker是脉冲式的,它会检查,看看是否_go已被设置为。如果_go仍然是,它将等待下一个脉冲。

如果如果来代替一个,那就只能等待一次(或者根本没有,如果_go已经),然后将继续在脉冲后,无论是新的_go的状态。

那么你如何使用Monitor.Wait()完全取决于你的具体需求。

+0

谢谢!这帮助了我。 – bitsmuggler 2012-01-16 19:30:23

3

这真的只是取决于情况。但首先,我们需要阐明监视器的工作原理。当一个线程继续通过Monitor.Pulse()发送一个线程的信号时,通常不能保证信号线程将会真正运行。这意味着其他线程可能在信号线程之前运行,并改变信号线程继续运行的条件。这意味着信号线程仍然需要检查在被唤醒后它是否安全(即while循环)。然而,某些罕见的同步问题可以让你做出这样的假设,即一旦线程被唤醒(即Monitor.Pulse()),其他线程就不能改变进行安全操作的条件(即if条件)。

1

我有一个问题在监视器的使用情况 - 为什么这里使用一个循环在 位置的一个if?

PulseWait,指出有疑问时喜欢while一个多if工作时有一个众所周知的规则。显然,在这种情况下,任何一个人都可以工作,但在几乎所有其他情况下,都需要while。事实上,使用while循环会产生错误结果的情况非常少(如果有的话)。这是这个一般规则的基础。作者使用了一个while循环,因为他试图坚持以前的模式。他甚至在同一篇文章中提供了该模板。这里,它是:

lock (_locker) 
    while (<blocking-condition>) 
    Monitor.Wait (_locker); 
0

最简单的方法编写正确的代码Monitor.Wait是假设系统将其视为“咨询”,并认为该系统可以任意唤醒任何等待的线程任何时候它可以获取锁,而不考虑Pulse是否已被调用。当然,系统不会这样做,但是如果一个程序正确使用WaitPulse,它的正确性不应该受到Wait任意提早无条件退出的影响。从本质上讲,应该把Wait作为告诉系统的一种手段“除非或直到其他人呼叫Pulse”,否则从这里继续执行将浪费时间。