【发布时间】: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