2012-12-19 16 views
1

我有6个线程在我的应用程序中不断运行。场景是:在C++中处理boost线程争用条件

一个线程不断获取消息并插入到消息队列中。其他4个线程可以被认为是连续从队列中获取消息并处理它们的工作者。另一个最终线程填充分析信息。

问题:

现在获得消息线程的睡眠持续时间是100ms。工作者线程是200ms。当我运行这个应用程序时,消息获取线程正在控制并插入队列,从而增加了堆。工作线程没有机会处理消息并释放它们。最终导致内存不足。

如何管理这种场景,以便为消息获取线程和工作者线程提供平等的机会。

感谢提前:)

+1

这被称为[读者 - 作家问题](http://en.wikipedia.org/wiki/Readers-writers_problem)。也许这个关键字可以帮助你进行搜索。通常你的作者(提取)会检查当前是否有读者在等待和暂停。另一方面,你的读者(工作人员)会检查是否有作者在等待。如果使用条件变量,实现基本功能非常简单。 – Zeta

回答

1

你的问题有点模糊,所以我可以给你这些指导方针,而不是代码:

  1. 维护双方的数据与互斥。在多线程consumer producer问题中,通常互相数据(程序中的消息)存在争用条件。一个线程试图在相互的内存位置进行写操作,而另一个线程则试图从相同的位置读取。读者阅读的信息可能会被破坏,因为作者在阅读过程中写过信息。您可以使用Mutex锁定相互的内存位置。每个线程都应该获得这个锁,以便能够读取或修改相互的数据。这样消费者过程将会绝对确保数据没有被修改。但是您应该注意获取此锁可能会阻止生产者线程,因此您应尽快释放锁。
  2. 使用条件变量来通知消费者线程。如果您不使用通知机制,则所有消费者线程都应主动检查将耗尽系统资源的数据生产。消费者线程应该很容易进入睡眠状态,因为知道生产者线程会在消息准备就绪时通知他们。

C++ 11中的线程库拥有实现用户生产者应用程序所需的所有功能。但是,如果你不能升级你的编译器,你也可以使用boost线程库。

1

您要使用受限制队列这充分时会阻塞线程试图排队,直到有更多的可用空间。

您可以使用concurrent_bounded_queue from tbb,或者简单地使用初始化为最大队列大小的信号量,并在入队和出队时递减。 boost :: thread本身不提供信号量,但是你可以使用锁和条件变量来实现它。

+0

+1用于提示TBB队列。 –

4

您需要向生产者线程添加背压。通常这将通过使用阻塞的消费者 - 生产者队列来完成。生产者将项目添加到队列中,消费者从队列中取出队列并处理它们。如果队列为空,消费者会阻塞,直到生产者添加一些东西到队列。如果队列已满,则生产者阻止,直到消费者从队列中获取项目。

4

我经常使用的一个流量控制系统是在启动时创建大量消息对象并且不再创建。 *对象存储在一个线程安全的阻塞的“池队列”中,并循环播放,由生产者/池从池中弹出,排队到其他阻塞队列中的消费者,然后在“消耗”时推回到池队列中。 (如果池清空,直到从消费者返回消息为止的生产者/块),并且消除连续的新/删除/ malloc/free,则会限制内存的使用,提供流量控制(012)。更复杂和更慢的有界队列不是必需的,并且所有队列只需足够大以容纳(已知)最大数量的消息。

使用'传统'阻塞队列不需要任何Sleep()调用。