繁体   English   中英

在C ++中使用pthreads实现线程池

[英]Pool of threads implementation using pthreads in C++

我在设计一个包含线程池的程序时遇到了麻烦。

我坚持的主要问题是当一个线程完成工作时,父必须在threadId上等待(这是父进程使用pthread_join等待线程)。 因为我们不知道哪个线程将首先完成,所以我无法找到解决问题的程序方法。

任何解释与一小段代码表示赞赏。

谢谢。

好吧,我不知道你的设置或要求,但你遇到了pthread_join()正好等待一个线程的问题,你实际上想要等待任何线程。

因此,最明显的结论是pthread_join对你没有帮助。 很抱歉说明显了,但我需要建立我的案例:-)

相反,你可能不得不提出另一个想法。 例如,您可以等待条件变量; 在线程退出之前将条件设置为“退出”。 主线程可以等待该条件,遍历线程以找出哪些已终止(可能多于一个),并最终重置条件。 条件互斥通常足以防止比赛。

除了设置条件之外,线程还可以将一些ID添加到退出线程列表中(您可以使用条件互斥锁来保护该列表),因此主线程只需要遍历该列表而不是检查每个线程。

伪代码:

initialize condition variable with status "not exited"
...
...
launch your threads
...
...
while (some threads are still running) do
   lock condition variable on "exited"
   iterate through threads, remove the ones that have exited
   unlock condition variable with new condition "not exited"

在你的线程内:

 ...
 do whatever it needs to do
 ...
 ...
 lock condition variable
 unlock condition variable with new condition "exited"
 /* end of thread */

池通常实现为在生产者 - 消费者队列上等待任务项的多个线程。 任务是从具有'run()'方法的Task类派生的对象。 无论哪个线程获得任务,它都会调用run(),并且当返回时,线程循环以从队列中获取另一个任务对象。

这吹走了任何线程微管理,并且可靠,安全地工作在我尝试过的每一个系统/语言上。

我知道完成通知的最灵活方式是线程在run()返回时调用'OnComplete'事件,或者可能是虚拟的'completed'方法,就在循环返回以获取下一个任务之前,任务作为参数。 例如,此方法/事件可以发出任务源线程正在等待的事件/ condvar / sema的信号,可以将完成的任务排队到原始线程或另一个线程,甚至只删除()任务,(也许是作业完全在线程池中完成)。

对于错误通知,我捕获run()抛出的任何未捕获的异常,并在调用完成方法/事件之前将异常存储在tast字段中。

除了那些保护生产者 - 消费者队列的锁之外没有锁(并且它们只需要足够长的时间来推送/弹出*任务)。

无论您使用哪种设计,请尽量不要:

1) continually create/terminate/destroy threads - avoidable overhead and tricky to manage
2) wait with Join() for any thread to terminate - just don't :)
3) loop around some 'poll thread status' to see if they're finished yet - gets it wrong
4) Move 'working/finished' threads into and out of containers with complicated locks - deadlock-in-the-making
5) use any other sort of micro-management - difficult, messy, error-prone, too many locks, unnecesary, avoidable

理想的线程池是你不知道哪个线程工作的地方。 实际上,通常甚至不需要保留对线程的任何引用。 双线伪threadPool:

TblockingQueue *inQueue=new TblockingQueue();
for(int i=0;i<CpoolDepth,i++) new Thread(inQueue);

如果您正在尝试实现线程池,请查看我几年前玩过的这种架构。 我在这里写了它: C ++中的线程池

对于非阻塞pthread_join,请参阅此SO讨论: 非阻塞pthread_join

如果你只是等待所有线程完成他们的工作,你可以一个接一个地等待它们:顺序无关紧要,并且没有理由使用条件。 此示例演示:

#include <memory.h>
#include <pthread.h>

#include <iostream>

using namespace std;

#define NTHREADS 10

void *thread(void *arg) {
    int *n = (int *) arg;
    sleep(10 - *n);
    cout << "Thread " << (*n) << endl;
    delete n;
    return NULL;
}

int main(int argc, char **argv) {
    pthread_t threads[NTHREADS];
    pthread_attr_t attr;
    memset(&attr, 0, sizeof(attr));
    int i;
    for (i=0; i<NTHREADS; i++) {
        int *p = new int;
        *p = i;
        pthread_create(threads + i, &attr, thread, p);
    }
    void *rval;
    for (i=0; i<NTHREADS; i++) {
        pthread_join(threads[i], &rval);
        cout << "Joined thread " << i << endl;
    }
    return 0;
}

虽然线程的顺序以与等待相反的顺序完成(即线程0最后完成,但我们先在线程0上等待),但主线程将不会退出,直到所有线程都完成。 无需条件。


暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM