如何重用线程 - pthreads c
Posted
技术标签:
【中文标题】如何重用线程 - pthreads c【英文标题】:How to resuse threads - pthreads c 【发布时间】:2012-04-20 04:39:27 【问题描述】:我正在使用 C 语言中的 pthread 进行编程。
我有一个父线程需要创建 4 个 ID 为 0、1、2、3 的子线程。 当父线程获取数据时,它将设置拆分数据并将其分配给 4 个单独的上下文变量 - 每个子线程一个。 子线程必须处理这些数据,同时父线程应该等待这些线程。 一旦这些子线程完成执行,它们将在其相应的上下文变量中设置输出并等待(以供重用)。 一旦父线程知道所有这些子线程都完成了这一轮,它就会计算全局输出并将其打印出来。 现在它等待新数据(子线程还没有被杀死,它们只是在等待)。
如果父线程获得更多数据,则重复上述过程 - 尽管已经创建了 4 个线程。
如果父线程接收到一个kill命令(假设一种特定的数据),它向所有的子线程发出指示并且它们自己终止。现在父线程可以终止了。
我是一名硕士研究生,我遇到了上述场景的需求。我知道这可以使用 pthread_cond_wait、pthread_Cond_signal 来完成。我已经编写了代码,但它只是无限期地运行,我不知道为什么。
我的猜测是,按照我的编码方式,我将场景过于复杂化了。了解如何实现这一点将非常有帮助。如果有需要,我可以发布我的代码的简化版本来展示我正在尝试做的事情(即使我认为我的方法有缺陷!)...
您能否告诉我有关如何使用 pthread 实现此场景的任何见解?
【问题讨论】:
您可能想看看this post,其中的答案描述了各种主/从场景。还有一个答案详细描述了如何使用 POSIX。 对于所有四个线程完成工作后所需的同步,您可以在这里查看:lambdacs.com/cpt/FAQ.html#Q292 【参考方案1】:从你的描述中可以看出,原理似乎没有问题。
我想您要实现的是一个工作池,应该有很多实现。如果您的线程正在执行的工作是大量计算(例如至少 CPU 秒左右),那么这种方案完全是矫枉过正。 POSIX 线程的现代实现足够高效,它们支持创建大量线程,真的很多,而且开销并不高。
如果您让您的工作人员通过共享变量、互斥锁等(而不是通过线程的返回值)进行通信,唯一重要的是您通过使用 pthread_create
的属性参数来分离启动线程.
一旦你的任务有了这样的实现,就可以测量了。只有这样,如果您的分析器告诉您在 pthread 例程中花费了大量时间,请开始考虑实现(或使用)工作池来回收线程。
【讨论】:
我的程序在使用这个池化概念时会创建 160000 个线程。如果我不使用线程池,那么这个数字会上升到 160 万——增加了 10 倍。还是不影响时代吗?? @TheFlyingDutchman,我怎么知道。你没有给我们任何暗示你的线程真正做了什么,他们为应用任务花费了多少时间以及有多少开销。测量一下,你就会知道。 (请分享。) @TheFlyingDutchman - 如果您在池中仅创建 16 个工作线程,并且不再创建,那么将永远只有 16 个工作线程。【参考方案2】:一个生产者-消费者线程和 4 个线程挂在它上面。想要将四个任务排队的线程组装了四个上下文结构,其中包含以及所有其他数据内容,一个指向“OnComplete”函数的函数指针。然后它将所有四个上下文提交到队列中,在执行此操作时自动将 taskCount 增加到 4,并等待事件/condvar/semaphore。
四个线程从 P-C 队列中获取上下文并开始工作。
完成后,线程调用“OnComplete”函数指针。
在 OnComplete 中,线程自动倒计时 taskCount。如果一个线程将其减为零,则表示 event/condvar/semaphore 和原始线程继续运行,知道所有任务都已完成。
安排它并不难,以便在一个任务中完成上下文的组装和同步等待,因此允许池同时为多个请求线程处理多个“ForkAndWait”操作。
我必须补充一点,像这样的操作在 OO 语言中非常容易。例如,最新的 Java 有一个 'ForkAndWait' 线程池类,它应该可以做这种事情,但是 C++(或者甚至是 C#,如果你喜欢农奴制的话)比普通的 C 更好。
【讨论】:
以上是关于如何重用线程 - pthreads c的主要内容,如果未能解决你的问题,请参考以下文章