【问题标题】:Waiting for all asynchronous consumers to complete before producer continues在生产者继续之前等待所有异步消费者完成
【发布时间】:2014-10-02 07:40:02
【问题描述】:

我们有一个非常接近生产者-消费者问题的问题集。实际用例是一个线程(生产者)运行一个目录列表(大约 2000 个条目),然后将这些条目提供给处理这些目录中特定文件的 4 个线程(消费者)。

我们试图解决的问题是如何让生产者线程等待最终消费者完成后再继续。一旦我们将所有文件都保存在内存中,就需要进行后处理,只有在读取所有文件后才能完成。

我们已经实现了一个非常简单的计数器解决方案,它基于轮询类计数器的繁忙等待(计数器由生产者递增,由消费者递减,由互斥锁保护):

   while(fileCnt > 0) {
     usleep(10000);
  }

这当然不是一个好的解决方案。

有没有办法通过条件/信号量/其他东西来做到这一点?

我们仅限于非 C++11 实现(基于 pthread)。

谢谢。

【问题讨论】:

  • 这些消费者是由一个受 cv+mtx 保护的队列提供的,并且谁的内容大小是谓词检查的一部分,对吗?
  • 典型的方法是有一个信号量,并预先加载队列大小的信号量(例如4、5或8,以允许生产者为消费者准备一些项目)。然后在信号量上上下上下表示剩余空间量,当信号量为零时,等待对方消费下一项)
  • @WhozCraig “我们仅限于非 C++11 实现(基于 pthread)。” --- 除非您建议增强变体。
  • 您还可以使用哪些其他库? Boost/RogueWave ?
  • @Jagannath 谁说过 c++11 ?标准pthreads.h 有条件变量和互斥体。 你在说什么?我从来没有忽略 OP 对 C++11 细节的限制。

标签: c++ linux multithreading pthreads posix


【解决方案1】:

嗯.. 对于一般情况,这实际上很难以有效的方式完成。如果您在提交第一个条目之前知道要向队列提交多少对象(就像您似乎所做的那样),那就更容易了:

将一个原子整数设置为要提交的对象数。在线程完成处理每个对象后调用的每个排队项目中加载一个回调。回调将 int 递减到零。当线程将其归零时,它会向同步对象发出信号,生产者在将其最后一个对象排队后正在等待该对象。

我还在考虑如果生产者在迭代某个列表并且在排队第一个项目之前不知道结尾在哪里:(

这种情况可能需要回调中的实际锁,以便生产者可以进入它并“原子地”检查所有排队的操作是否已完成,如果没有,则在退出锁后等待同步对象。如果同步对象保持状态会更安全,例如。一个信号量,以便在退出锁之后但在等待之前发出的信号不会错过,(??不确定如何使用 condvar 安全地做到这一点??)。

【讨论】:

  • 我们使用 2 个互斥对象实现了上述操作,并且效果很好。谢谢。
猜你喜欢
  • 1970-01-01
  • 2014-10-16
  • 2021-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多