pthread退出时运行函数

Run function when pthread exits

本文关键字:函数 运行 退出 pthread      更新时间:2023-10-16

我有一个C++应用程序,我在其中创建pthread来运行用户提供的函数。当线程退出时,我希望能够以某种方式得到提醒,这样我就可以将其从用于保留线程的pthread数组中删除。有没有办法做到这一点,或者函数应该设置一些"神奇的值"。因为我产生pthreads的主要代码是在某种运行循环中,所以我可以很容易地检查退出条件。


此外,使用std::vector<pthread_t>来跟踪我的线程是否是一种过载?线程数量不一定是任何类型的常量,可能有很多线程或很少线程在运行。或者,是否有另一个STL容器可以用于这些添加和删除(添加总是在一端,删除几乎在任何地方)。是否有其他结构可以跟踪pthreads?堆栈或列表就在这里吗?还是一个标准的C数组,有一个慷慨的最大优点?由于问题的性质,我还可以维护一个固定大小的工作线程数组,将必须执行的用户函数传递给这些线程。这是一个好的解决方案吗?

很抱歉出现这个长期困惑的问题,但我只在动态语言中处理过线程,这永远不会成为问题。


编辑(2012年8月3日):在阅读了@jojojapan的答案后,我决定使用某种线程池。在我的结构中,我有一个生产者(运行循环中的一个线程)和许多消费者(池中的工作线程)。有没有一个数据结构是为多线程的一个生产者多个消费者所使用的?或者我可以只使用带有pthread_mutex_tstd::queue吗?

  1. 您可能需要考虑的一个选项是,线程完成任务后,不实际结束并删除它们,而是保持它们的活动状态,并让它们等待新任务分配给它们你可以通过做两件事来实现这一点:

    1. 在线程中使用(几乎)无限循环
    2. 使用并发队列或其他技术,让它们等待另一个线程发出信号。设计模式和策略在几个SO问题中进行了讨论,例如本问题
  2. 如果您真的想在线程结束后发送信号,那么可以使用pthread_cond_t并在线程到达其return语句之前对其调用pthread_cond_signal。当然,这是假设有其他线程在运行,等待这些信号,并通过从向量中删除相应的线程来对其进行操作。有关用法的详细信息,请参阅相应的手册页,也可在本SO帖子中找到。

编辑与评论和问题编辑部分相关的内容:

  1. 关于工作线程的数量:这取决于线程使用最多的资源。如果这些线程主要做的是计算和一点内存访问,换句话说,如果它们是CPU绑定的,那么使用尽可能多的线程是有意义的(特别是,有一定数量的内核,以及每个内核可以运行的(硬件)线程数,然后它们开始相互减慢速度。你正在创建的线程(软件线程)应该是一样多,或者可能更多(根据@Tudor在这里的说法,最多是硬件线程的两倍是合理的)。但是,如果线程大量使用内存(内存绑定)或硬盘(IO绑定)或其他资源,如网络、NFS或其他服务器,则可能需要减少线程数量,以便(a)不使它们相互阻塞,(b)不在某些资源上施加不合理的过多负载。确定正确的线程数量可能是一个实验问题,保持数量可配置通常是一个好主意。

  2. 关于存储工作任务的最佳数据结构:我在上面引用的帖子的评论中提到的并发有界队列可能非常好。不过我自己还没试过。但是,如果你想保持简单,如果你使用信号/互斥技术正确地保护它们,标准的std::queue,甚至简单的std::vector都不是一个糟糕的选择。

考虑完全更改策略并使用现有的线程池库。他们会为你做这项工作,你会省去很多不那么有趣的调试。

Boost.线程池是众多链接之一。

一个简单的方法就是使用管道。

在生成线程之前打开管道。将管道fd作为线程数据的一部分传递。在线程退出之前,让它将其pthread_self()写入管道。在管道的读取端有主螺纹或单独螺纹。它读取死线程的tid并立即执行pthread_join。(如果它是一个单独的收割者线程,它可以直接阻塞管道读取;如果它是主线程,则将其作为选择/轮询或其他线程的一部分。)

这使您可以灵活地在不需要的情况下根本不使用数据结构来保存TID。如果你确实想保存它们,那么列表或地图是比矢量更好的选择。

如果您有main启动线程和一个单独的"reaper"线程来收集它们,并且您想将它们保存在某个结构中,那么您需要在两者之间同步对该结构的访问。