我正在尝试使用C++11标准库中的多线程功能,并设想以下情况。
我有一个父类,它维护一个线程队列。所以类似于:
std::queue<MyMTObject *> _my_threads;
类MyMTObject
包含std::thread
对象。队列的固定大小为5,类最初以队列已满开始。
由于我有工作要处理,我启动线程并将它们从队列中删除。我想要的是在作业完成时得到一个通知,以及指向MyMTObject
的指针,这样我就可以将它们重新插入队列中,并使它们再次可用。
我基本上有两个问题:
1:这个主意好吗?我知道我没有具体说明,但从广义上讲。当然,我将使用互斥锁来控制对队列的所有访问。
2:有没有一种方法可以在不使用像Qt
或boost
这样的外部库的情况下实现这种通知机制。
对于重复项,我确实在网站上搜索了一下,但找不到任何适合管理线程集合的内容。
我不确定是否需要提及这一点,但std::thread
对象不能重复使用。通常,保留std::thread
引用的唯一原因是对线程std::thread::join
的引用。如果您不打算稍后加入线程(例如分派到线程并等待完成),通常建议std::thread::detach
it.
如果你试图为一个线程池保留线程,那么在std::queue
上有每个线程块并从队列中提取要处理的对象可能会更容易。使用std::mutex
和std::condition_variable
实现这一点相对容易。它通常提供良好的吞吐量,但为了更好地控制调度,您可以为每个线程保留一个单独的std::queue
。
分离线程和创建工作队列还有一个额外的好处,即它避免了冗余地请求操作系统创建新线程,这会增加开销并增加总体资源使用率。
我认为您可以尝试部署某些版本的Reactor模式。因此,您可以启动一个额外的控制线程,在这些工作者之后清理。现在,您将创建一个ThreadSafeQueue
,用于将事件从工作线程传递到控制线程。这个队列的实现方式应该是,您可以在它上面select
,并在另一端等待任何活动(例如,一些线程终止并调用queue.push
)。
总而言之,我认为这是一个非常优雅的解决方案。我确实增加了一个额外线程的开销,但这个线程大部分时间都在睡觉,偶尔只醒一次,以便在工作者之后清理。
在Posix中没有优雅的方法可以做到这一点,C++线程模型几乎是Posix上的一个薄包装。
你可以加入一个特定的线程(一次一个),也可以等待未来——再一次,一个未来。
避免循环的最佳方法是使用一个条件变量,并在所有线程即将退出之前让它们在该变量上发出信号(以及通过设置某种每线程标志来指示哪个线程刚刚退出)。收割者会注意到信号并检查旗。
问题是这个解决方案需要线程协作。但我知道没有比这更好的了。