如何使用带有 pthreads 的线程池?

Posted

技术标签:

【中文标题】如何使用带有 pthreads 的线程池?【英文标题】:How to utilize a thread pool with pthreads? 【发布时间】:2011-10-20 17:38:22 【问题描述】:

我有一个作业队列,我想创建一个由四个线程组成的池,我可以在其中投入我的作业。我坚持的是如何制作线程并在没有工作的情况下让它们暂停。

JOB QUEUE        | job1 | job2 | job3 | job4 | ..

THREAD POOL      | thread1 | thread2 | thread3 | thread4 |

在初始化点创建我当前拥有的线程:

for (t=0; t<num_of_threads; t++)
    pthread_create(&(threads[t]), NULL, doSth2, NULL);

其中num_of_threads=4doSth2 是一个内部没有任何内容的函数。 因此,一旦我创建了 4 个线程并使用 doSth2 完成了它们,我怎样才能在不杀死它们的情况下给它们新的工作?

【问题讨论】:

【参考方案1】:

线程池的关键是队列。这是我开发的线程池的修改函数。

将元素放入队列

void queue_add(queue q, void *value)

    pthread_mutex_lock(&q->mtx);

    /* Add element normally. */

    pthread_mutex_unlock(&q->mtx);

    /* Signal waiting threads. */
    pthread_cond_signal(&q->cond);

从队列中获取元素

void queue_get(queue q, void **val_r)

    pthread_mutex_lock(&q->mtx);

    /* Wait for element to become available. */
    while (empty(q))
        rc = pthread_cond_wait(&q->cond, &q->mtx);

    /* We have an element. Pop it normally and return it in val_r. */

    pthread_mutex_unlock(&q->mtx);

【讨论】:

谢谢。我现在明白了。池中的每个线程都应该从队列中串行读取。但是,如果队列为空,您如何暂停线程以便它们不会占用 CPU? @Pithikos pthread_cond_wait 阻止,直到有人 (queue_add) 发出信号 cond 抱歉这么晚才打开,但是如果 queue_get 锁定了 mtx 然后循环,如果 mtx 被锁定,你怎么能添加一个项目?锁不应该在循环之后(例如循环 -> 锁定 -> 弹出 -> 解锁)吗? 不久前我知道-回答@AlexandreGomes-pthread_cond_wait(来自人[linux.die.net/man/3/pthread_cond_wait])在等待时解锁互斥锁,供其他线程使用,并返回再次锁定它。因此,互斥体作为参数传递。【参考方案2】:

作为 cnicutar 答案的替代 riff,您可以使用 POSIX message queues 来处理内核中的同步问题。系统调用会有一些小的开销,这可能是也可能不是问题。它非常小,因为内核正在执行您必须手动执行的所有操作。

消费者线程可以在mq_receive 上阻塞,如果您创建一种特殊类型的队列消息,它可以很容易地告诉线程何时关闭。

【讨论】:

以上是关于如何使用带有 pthreads 的线程池?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中正确销毁线程池

基于pthread的线程池实现

如何终止线程池中的所有预分配线程?

在多线程情况下,如何获取当前线程id

线程池学习笔记

为啥线程没有在线程池中重用?