gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-30 00:00:32 31 4
gpt4 key购买 nike

我在 ASP.NET 中有一个生产者-消费者场景。我设计了一个Producer 类,一个Consumer 类和一个用于保存共享对象并负责Producer 和Consumer 之间通信的类,我们称它为Mediator。因为我在启动时 fork 执行路径(在父对象中)并且一个线程会调用 Producer.Start() 而另一个线程会调用 Consumer.Start(),我需要将 Mediator 的引用传递给 ProducerConsumer(通过 Constructor)。 Mediator 是一个智能类,它将优化许多事情,例如它的内部队列的长度,但现在将其视为循环阻塞队列。 Producer 会将新对象排队Mediator,直到队列满为止,然后Producer 会阻塞。 Consumer dequeues 来自 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();
}

在 Mediator 内部,每次入队出队时,我都会使用this.Pulse(),这样等待的线程就会收到信号并继续它们的工作.

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

谢谢

最佳答案

这里没有太多代码可以继续,但我最好的猜测是你有一个 live-lock问题。如果 Mediator.PulseMediator.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();
}
}
}

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

关于c# - Monitor.Wait() 和 Monitor.Pulse() 的线程问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3956127/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com