Monitor.Wait - while或if?

时间:2012-01-16 19:10:57

标签: c# multithreading monitor

目前,我正在学习多线程考试。我看了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!!!");
  }
}

5 个答案:

答案 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的地方?

使用PulseWait时,有一个众所周知的规则,即当有疑问时,while更喜欢if。显然,任何一个都可以在这种情况下工作,但在几乎所有其他情况下都需要while。事实上,使用while循环的情况很少(如果有)会产生不正确的结果。这是这个一般规则的基础。作者使用了while循环,因为他试图坚持使用经过验证的模式。他甚至在同一篇文章中提供了模板。这是:

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

答案 4 :(得分:0)

使用Monitor.Wait编写正确代码的最简单方法是假设系统将其视为“建议”,并假设系统可以在任何时候获取锁定时任意唤醒任何等待线程,而不考虑是否已调用Pulse。当然,系统通常不会这样做,但如果某个程序正确使用WaitPulse,则{{1}不应影响其正确性}无条件地提前任意退出。从本质上讲,应该将Wait视为告诉系统的一种方式“除非或直到其他人打电话给Wait”,否则继续执行此处将是浪费时间。