【问题标题】:Do I need a lock if I have EventWaitHandle如果我有 EventWaitHandle 我需要锁吗
【发布时间】:2017-11-27 09:45:30
【问题描述】:

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);
      }
    }
  }
}

【问题讨论】:

  • 我看不出删除lock 可以改变这个例子中的执行顺序。
  • 不需要锁,两个 AutoResetEvents 之间的乒乓球提供了同步,确保线程不能同时访问变量。 WaitOne() 调用提供了一个内存屏障,确保变量更新对另一个线程可见。这些偶然的障碍不是很漂亮,但并不少见。您强烈支持使用 Barrier 类,它的 SignalAndWait() 方法使此代码更易于理解。而且效率更高。看得懂的代码避免了线程错误,高效的代码让每个人都开心。

标签: c# multithreading thread-synchronization


【解决方案1】:

你是对的。

这类问题不能简单地通过反复试验来测试。最好用逻辑思维来分析它们:

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

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

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

_ready.WaitOne();

_go.Set();

而在Work() 中对_message 的访问总是介于两者之间

_go.WaitOne();

_ready.Set();

因此,其中一个线程在访问_message之前总是会等待另一个线程,因此不需要锁。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2010-10-14
      • 1970-01-01
      • 1970-01-01
      • 2022-11-20
      • 1970-01-01
      • 1970-01-01
      • 2016-01-10
      • 1970-01-01
      • 2022-08-04
      相关资源
      最近更新 更多