C# 监视器。请稍候,如果是?

C# 监视器。请稍候,如果是?,c#,multithreading,monitor,C#,Multithreading,Monitor,目前,我正在学习多线程考试。我读书。我有一个关于监视器使用的问题-为什么这里使用循环来代替if lock (_locker) { while (!_go) //why while and not if? Monitor.Wait (_locker); // _lock is released // lock is regained ... } 我认为,一个if就足够了 恐怕我不完全理解这篇文章 //编辑 示例代码: class SimpleWaitPulse { st

目前,我正在学习多线程考试。我读书。我有一个关于监视器使用的问题-为什么这里使用循环来代替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!!!");
  }
}

这要视情况而定。在这种情况下,代码只是等待
\u go
变为true

每次
\u locker
被触发时,它都会检查
\u go
是否已设置为true。如果
\u go
仍然为false,它将等待下一个脉冲

如果使用If而不是一段时间,它将只等待一次(如果
\u go
已经为true,则根本不会等待),然后在脉冲后继续,而不管
\u go
的新状态如何


因此,如何使用Monitor.Wait()完全取决于您的具体需要

这取决于具体情况。但首先,我们需要澄清监视器是如何工作的。当一个线程继续通过Monitor.Pulse()向一个线程发送信号时,通常无法保证发出信号的线程下一步是否会实际运行。这意味着其他线程可以在发出信号的线程之前运行,并更改发出信号的线程可以继续运行的条件。这意味着发出信号的线程在被唤醒(即while循环)后仍需要检查是否安全才能继续。但是,某些罕见的同步问题允许您假设,一旦一个线程被信号唤醒(即Monitor.Pulse()),就没有其他线程能够更改安全继续的条件(即if条件)。

我写了一篇文章,这篇文章可能会有所帮助:

现在发生的事情远不止是显而易见的

我有一个关于监视器使用的问题-为什么这里使用循环 if的位置

lock (_locker)
{
  while (!_go) //why while and not if?
    Monitor.Wait (_locker);  // _lock is released
  // lock is regained
  ...
}
使用
Pulse
Wait
时有一条众所周知的规则,即当有疑问时,宁愿使用
而不是
if
。显然,在这种情况下两种方法都可以,但在几乎所有其他情况下都需要
,而
是必需的。事实上,使用
while
循环会产生错误结果的情况很少(如果有的话)。这是这一一般规则的基础。作者使用了
while
循环,因为他试图坚持久经考验的真实模式。他甚至在同一篇文章中提供了模板。这是:

lock (_locker)
  while ( <blocking-condition> )
    Monitor.Wait (_locker);
锁(\u锁柜)
而()
监视器。等待(_locker);

使用
监视器写入正确代码的最简单方法是假设系统将其视为“建议”,并假设系统可以在任何时候获取锁时任意唤醒任何等待线程,而不考虑是否调用了
脉冲。当然,系统通常不会这样做,但是如果程序正确地使用了
Wait
Pulse
,那么
Wait
调用会无缘无故地提前退出,不会影响其正确性。本质上,我们应该把等待看作是告诉系统“如果”只检查一次“那么,除非或直到其他人调用脉冲,否则在这里继续执行将是浪费时间”的一种方式。“while”循环将继续检查。如果你不等待。等待。你好,谢谢你的解释。但我认为Monitor.Wait操作只会执行一次。它将等待脉冲信号。所以我暂时看不出有什么理由:-(这取决于程序的其余部分,例如
\u go
的确切含义,以及您何时设置它。您好,斯维克-谢谢您的回答。我添加了示例。pro,这实际上取决于您希望等待事件发生的次数。通常,在锁定后内存中会有某种类型的修改,如果您不想这样做的话o“观察”该修改一次,然后您可以使用if(例如,您发送一条消息并等待一个响应)。如果您想持续“观察”该修改,则在while循环中进行(即,您正在监视消息流中的大量消息)。