【问题标题】:Waiting for all Consumers to be in the waiting state in a Producer and Multi-Consumer implementation在生产者和多消费者实现中等待所有消费者处于等待状态
【发布时间】:2019-11-07 06:41:25
【问题描述】:

背景

我已经用 C# 实现了一段代码,它相当于一个生产者和许多消费者使用 Monitor 的 Wait 和 PulseAll 方法。

我想为生产者提供在生产之前等待的选项,直到所有消费者都在等待。

这是消费者端的简化实现:

lock (_lock)
{
    while (! _condition)
    {
        Monitor.Wait(_lock);
    }
}

这是生产者端的简化实现:

lock (_lock)
{
    _condition = true;
    Monitor.PulseAll(_lock);
}

这是一种众所周知的模式,在我的情况下非常有效并且效果很好。

问题

在某些情况下,我希望能够让生产者在调用上面的生产者代码之前等待,直到所有消费者都在 Monitor.Wait() 调用中。

单一消费者的解决方案概念

让我们针对单个消费者的情况简化问题。 该解决方案要求生产者等待一个额外的同步对象,消费者可以通过其对Monitor.Wait() 的入口自动发出信号。

多消费者的解决方案概念

概括上述解决方案,所有消费者都需要访问一个线程安全计数器,该计数器使用消费者数量进行初始化。

每个消费者都会自动调用Monitor.Wait() 并递减计数器。同样在原子调用中,每个消费者将检查递减后计数器是否为零,如果是,则重新初始化计数器并向生产者发出信号。

总结

在 C# 中的 Producer 和 Multi-Consumer 实现中,我需要让生产者在生产之前等待所有消费者处于等待状态。

我还没有找到一种基于 Monitors 来实现它的方法。

我更喜欢基于 Monitors 的解决方案,但如果采用完全不同的方法可以使这更简单,那也很棒。

【问题讨论】:

  • 生产者等待每个消费者都处于等待状态的重要原因是什么?
  • 嗯,是的,您已经描述了您的解决方案,应该可以正常工作。你想要一个变量“工作消费者”,消费者根据他们的状态在你的锁中更新。当达到 0 时,向生产者发出信号。不要使用两个锁,这应该很简单。你有什么问题?
  • @Voo 这不起作用。在消费者方面,我改变了等待:\
  • @David 什么不起作用?保持计数器准确很简单(在工作回调之前递增,之后递减并检查是否为 0),然后它只是向生产者发出信号。
  • @Voo 对不起,评论在完成前滑倒了。在消费者方面,我现在有这个:``` lock (_lock) { while (!_condition) { // added _waiting++; Monitor.PulseAll(_lock); // 结束 Monitor.Wait(_lock); _等待 - ; } } ``` 并且在生产者端:``` lock (_lock) { // 添加 while (_waiting != 1) { Monitor.Wait(_lock); } // 结束添加 _condition = true; Monitor.PulseAll(_lock); } ```

标签: c# multithreading monitor producer-consumer thread-synchronization


【解决方案1】:

您可以为此使用CountdownEvent,消费者应该发出事件信号,然后生产者可以等待进入锁,直到倒计时达到零。

【讨论】:

  • 感谢@Stephen Jennings。我试过了,找不到重置倒计时事件的正确位置。在一个地方它导致了死锁,而在另一个地方,在生产者等待它之前,reset 使信号无效。你能提出一个代码更新来展示这个想法吗?
  • 为什么生产者等待所有消费者都处于等待状态很重要?如果生产者产生一个没有等待消费者的值,会出现什么问题?
  • 可能是我对需求的分析不正确。我现在正在审查。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-16
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多