Monitor.Wait()和Monitor.Pulse()的线程问题

Xaq*_*ron 4 c# asp.net multithreading

我在ASP.NET中有一个生产者 - 消费者场景.我设计了一个Producer类,一个Consumer类和一个类来保存共享对象并负责Producer和Consumer之间的通信,让我们调用它Mediator.因为我在启动时(在父对象中)分叉执行路径,并且一个线程将调用Producer.Start()并且另一个线程调用Consumer.Start(),我需要传递Mediator对两者ProducerConsumer(via Constructor)的引用.Mediator是一个智能类,它将优化许多内容,如内部队列的长度,但现在将其视为循环阻塞队列.Producer排入新的对象Mediator,直到队列变满,然后Producer将阻塞.从中Consumer 取出物体Mediator直到队列中没有任何内容.对于线程之间的信令,我在Mediator类中实现了两个方法:Wait()Pulse().代码是这样的:

Class Mediator
{
  private object _locker = new object();

  public void Wait()
  {
    lock(_locker)
      Monitor.Wait(_locker);
  }

  public void Pulse()
  {
    lock(_locker)
      Monitor.Pulse(_locker);
  }
}

// This way threads are signaling:

Class Consumer
{
  object x;
  if (Mediator.TryDequeue(out x))
    // Do something
  else
    Mediator.Wait();
}
Run Code Online (Sandbox Code Playgroud)

在Mediator中我this.Pulse()每次出入队列或出队时都会使用,这样等待线程就会发出信号并继续工作.

但我遇到死锁,因为我从未使用过这种设计信号线程,我不确定设计是否有问题,或者我在其他地方做错了什么?

谢谢

Bri*_*eon 8

这里没有太多代码可以继续,但我最好的猜测是你有一个锁定问题.如果Mediator.Pulse在此之前调用,Mediator.Wait则即使队列中存在某些内容,信号也会丢失.以下是实现阻塞队列的标准模式.

public class BlockingQueue<T>
{
  private Queue<T> m_Queue = new Queue<T>();

  public void Enqueue(T item)
  {
    lock (m_Queue)
    {
      m_Queue.Enqueue(item);
      Monitor.Pulse(m_Queue);
    }
  }

  public T Dequeue()
  {
    lock (m_Queue)
    {
      while (m_Queue.Count == 0) 
      {
        Monitor.Wait(m_Queue);
      }
      return m_Queue.Dequeue();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意Monitor.Wait,只有在队列为空时才会调用它.还要注意它是如何在while循环中调用的.这是因为a Wait没有优先权,Enter因此Dequeue即使呼叫Wait准备好返回,进入的新线程也可能占用最后一个项目.如果没有循环,线程可能会尝试从空队列中删除项目.