【问题标题】:C# Producer-Consumer pattern with Monitor.Wait and Monitor.Pulse带有 Monitor.Wait 和 Monitor.Pulse 的 C# 生产者-消费者模式
【发布时间】:2014-02-23 07:14:06
【问题描述】:

考虑以下阻塞生产者和消费者线程的实现:

static void Main(string[] args)
{
  var syncRoot = new object();
  var products = new List<int>();

  Action producer = () => {
    lock (syncRoot)
    {
      var counter = 0;
      while (true)
      {
        products.Add(counter++);
        Monitor.Pulse(syncRoot);
        Monitor.Wait(syncRoot);
      }
    }};

  Action consumer = () => {
    lock (syncRoot)
      while (true)
      {
        Monitor.Pulse(syncRoot);
        products.ForEach(Console.WriteLine);
        products.Clear();
        Thread.Sleep(500);

        Monitor.Wait(syncRoot);
      }};

  Task.Factory.StartNew(producer);
  Task.Factory.StartNew(consumer);

  Console.ReadLine();
}

假设当 Producing 线程进入 Monitor.Wait 时,它会等待两件事:

  1. 用于从消费者线程发送脉冲,并且
  2. 用于重新获取锁

在上面的代码中,我在 PulseWait 调用之间进行了消耗性工作。

所以如果我这样写我的消费线程(等待前立即脉冲):

  Action consumer = () =>
  {
    lock (syncRoot)
      while (true)
      {
        products.ForEach(Console.WriteLine);

        products.Clear();
        Thread.Sleep(500);

        Monitor.Pulse(syncRoot);
        Monitor.Wait(syncRoot);
      }
  };

我没有注意到行为有任何变化。有什么指导方针吗?我们通常应该在Wait 之前立即Pulse 还是在性能方面可能存在差异?

【问题讨论】:

  • 如果使用 .NET 4 或更高版本,请查看 System.Collections.Concurrent 命名空间以获取新的并发集合 (msdn.microsoft.com/en-us/library/…)
  • BlockingCollection 例如,stackoverflow.com/questions/21357933/…
  • @Jason @L.B.集合很棒,但是有比共享集合更复杂的生产者/消费者场景。这就是为什么我想更多地了解Monitor 方法的工作原理。

标签: c# concurrency producer-consumer monitors


【解决方案1】:
  • Pulse then Wait 与 Wait then Pulse 几乎相同,因为它们在无限循环中运行。 Pulse,Wait,Pulse,Wait 和 Wait,Pulse,Wait,Pulse 差不多

  • 通常,等待更改的线程使用Wait,进行更改的线程使用Pulse。一个线程可以同时做这两件事,但一般做法取决于具体情况。

  • 给出的代码是在按住锁的同时处于休眠状态。出于学习/模拟目的,这很好,但生产代码通常不应该这样做。您可以将超时传递给Wait,这很好,并且在等待期间不会持有锁。

  • 一般来说,Monitor 被认为是低级同步原语,建议使用更高级别的同步原语。了解像 Monitor 这样的低级原语很好,但普遍的看法是,对于几乎任何实际场景,都可以使用一些更不容易出错的更高级别的原语,不太可能隐藏一些棘手的比赛场景,并且更容易在某人身上阅读else 的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-14
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    • 2011-10-27
    相关资源
    最近更新 更多