如果我有EventWaitHandle,是否需要锁定?

时间:2017-11-27 09:45:30

标签: c# multithreading thread-synchronization

albahari atricle学习多线程。 我需要在下面的示例中使用锁_locker吗?我想不,因为_messageEventWaitHandle保护。我是对的吗?

class TwoWaySignaling
{
  static EventWaitHandle _ready = new AutoResetEvent (false);
  static EventWaitHandle _go = new AutoResetEvent (false);
  static readonly object _locker = new object();
  static string _message;

  static void Main()
  {
    new Thread (Work).Start();

    _ready.WaitOne();                  // First wait until worker is ready
    lock (_locker) _message = "ooo";
    _go.Set();                         // Tell worker to go

    _ready.WaitOne();
    lock (_locker) _message = "ahhh";  // Give the worker another message
    _go.Set();
    _ready.WaitOne();
    lock (_locker) _message = null;    // Signal the worker to exit
    _go.Set();
  }

  static void Work()
  {
    while (true)
    {
      _ready.Set();                          // Indicate that we're ready
      _go.WaitOne();                         // Wait to be kicked off...
      lock (_locker)
      {
        if (_message == null) return;        // Gracefully exit
        Console.WriteLine (_message);
      }
    }
  }
}

2 个答案:

答案 0 :(得分:3)

你是对的。

这些问题无法通过反复试验进行简单测试。最好用逻辑思维来分析它们:

  • 哪个线程运行哪个代码?
  • 其他线程现在可能会发生什么?
  • 如果另一个线程获得更多CPU时间会怎样?等

主线程只执行Main()中的代码,而工作线程只执行Work()中的代码。这很简单。

如果您查看关键资源的访问方式,您会注意到_message中对Main()的访问始终在

之间
_ready.WaitOne();

_go.Set();

_message中对Work()的访问始终在

之间
_go.WaitOne();

_ready.Set();

因此,在访问_message之前,其中一个线程将始终等待另一个线程,并且不需要锁定。

答案 1 :(得分:0)

您已停止线程同时访问_message变量。你在这里的逻辑是自给自足和可预测的,但情况并非总是如此。有时你会从其他地方读取并且流程不是完全可控的,在这种情况下你需要锁定关键变量。