通过谷歌搜索似乎并不是真的建议使用表来实现生产者/消费者模式。最棘手的部分是拥有多个消费者
我不知道为什么。如果不是让多个进程/线程试图声明记录而我们应该确保它们不会声明相同的记录,那么让一个消费者获取记录,将它们传递给分叉进程是不一样的哪个处理并最终更新相关记录?
似乎这种设计与拥有多个消费者具有相同的结果,但没有缺点
我误解了一些事情,例如交易明智,锁定等?
答案 0 :(得分:1)
我发现与使用单个线程安全队列的多个使用者一起工作要容易得多。该计划的一般结构是:
var queue = some thread-safe queue
// multiple consumer threads that all do this
consumer:
while (queue.Take(item))
{
process(item);
}
请注意,队列的Take
方法会进行非繁忙等待(通常使用某种monitor。
生产者将东西添加到队列中:
producer:
while (items available from input)
{
queue.Add(item);
}
对我来说,这是一个更简单的设计,因为我只需要设置一次。设计队列数据结构使其支持多个生产者和多个消费者。它为您处理所有同步。
如果以另一种方式执行此操作,使用单个使用者线程为队列提供服务并根据需要触发工作线程,则会变得混乱。使用者线程必须跟踪当前正在运行的工作线程数,并在工作者完成时接收通知。工作者线程不仅要关心处理项目,还要关注他们何时完成工作。结果是您的代码要么不断创建和销毁线程,要么您使用显式同步和线程间通信机制来基本上挂起和重新启动线程。所有这一切都是可能的,但它比通过支持非忙等待的单个线程安全队列进行通信要复杂得多。
有变化。您可以使用单个线程从输入中获取项目并触发工作线程,当要处理的项目数超过可用工作线程数时,将其他工作者或工作项排队。这只是制作人的另一个复杂程度,并没有真正改变事物。
我不能说哪个更有效率,尽管它可能是一个没有实际意义的点。与他们无关的总数相比,执行时间的任何差异都可能很小。对我而言,我的程序正确且易于理解更为重要。与我自己的使用大量显式同步的自定义调度程序相比,具有共享队列的简单生产者/消费者模型更容易编码,理解和证明正确。
答案 1 :(得分:0)
多个消费者线程争用的代价是他们必须在等待锁消耗时阻塞。使用您建议的模式为多个线程服务,线程仍然必须在等待使用时阻塞。只是他们正在等待单个消费者"而不是等待一个简单的锁。由于"单一消费者"将比简单的锁更复杂,效率更低,容易出错。