我在设计一个包含线程池的程序时遇到了麻烦。
我坚持的主要问题是当一个线程完成工作时父进程必须等待threadId(这是父进程使用pthread_join等待线程)。因为我们不知道哪个线程将首先完成,所以我无法找到解决问题的程序方法。
对一小段代码的任何解释都表示赞赏。
感谢。
答案 0 :(得分:1)
好吧,我不知道你的设置或要求,但是你遇到了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 */
答案 1 :(得分:1)
池通常实现为在生产者 - 消费者队列上等待任务项的多个线程。任务是从具有'run()'方法的Task类派生的对象。无论哪个线程获得任务,它都会调用run(),并且当返回时,线程循环以从队列中获取另一个任务对象。
这会打乱任何线程微观管理,并且可靠,安全地运行在我尝试过的每个系统/语言上。
我知道完成通知的最灵活的方式是线程在run()返回时调用'OnComplete'事件,或者可能是虚拟的'completed'方法,就在循环返回到下一个之前任务,以任务为参数。例如,此方法/事件可以发出任务源线程正在等待的事件/ condvar / sema的信号,可以将完成的任务排队到原始线程或另一个线程,甚至只删除()任务,(也许是job完全在线程池中完成。)
对于错误通知,我捕获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);
答案 2 :(得分:0)
如果您正在尝试实现线程池,请查看我几年前玩过的这种架构。我在这里写了:Thread Pooling in C++
对于非阻塞pthread_join,请参阅此SO讨论:Non-blocking 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上等待),但主线程将不会退出,直到所有线程都完成。无需条件。