多个线程之一的Pthread_join

我的问题是类似于如何检查线程是否在使用pthread时被终止? 。 但我没有得到答案。

我的问题是…我创build一定数量的线程说n。 只要main检测到任何一个线程的退出,它就会创build另一个线程,从而保持并发度为n等等。

主线程如何检测线程的退出。 pthread_join等待一个特定的线程退出,但在我的情况下,它可以是任何一个n线程。

谢谢

最显而易见的是,没有按照aix的说法重构你的代码,就是让每个线程设置一些东西来表明它已经完成(可能是所有线程之间共享一个数组中的一个值,每个工作者线程一个槽),然后发送一个条件变量。 主线程在条件变量上等待,每次唤醒时,处理所有表示自己已完成的线程:可能有多个线程。

当然,这意味着如果线程被取消,你永远不会得到信号,所以使用取消处理程序或不要取消线程。

有几种方法可以解决这个问题。

一种自然的方式是拥有一个固定大小的线程池,并有一个主线程将放置任务的队列,工作人员将从中获取任务并处理它们。 这将保持不变的并发度。

另一种方法是将初始值设置为n的信号量。 每次创建工作线程时,信号量的值都需要递减。 每当一个工人即将终止,它将需要增加(“后”)信号量。 现在,等待主线程中的信号量将被阻塞,直到剩下的工人数量不足n ; 然后会产生一个新的工作线程,等待重新开始。 既然你不会在worker上使用pthread_join ,他们应该被分离( pthread_detach )。

如果要通知退出的线程(通过pthread_exit或cancel),可以使用带有pthread_cleanup_push的处理程序来通知退出子进程的主线程(通过条件变量,信号量或类似方法),以便它可以等待,或者干脆开始一个新的(假设孩子先被分离)。

或者,我建议让线程等待更多的工作(如@aix所示),而不是结束。

如果你的父线程需要做其他事情,那么它不能一直在pthread_join上被阻塞,你需要一种方法从子线程向主线程发送消息,告诉它调用pthread_join 。 有许多IPC机制可以用于此目的。

当一个子线程完成它的工作时,它会通过IPC发送一些消息给主线程,说“我完成了我的工作”并且还传递了自己的线程ID,然后主线程知道调用该线程ID上的pthread_join

一个简单的方法是使用管道作为(工作)线程和主线程之间的通信通道。 当一个线程终止时,它将结果(在下面的例子中是线程标识符)写入管道。 主线程在管道上等待,一旦可用,就从中读取线程结果。

与互斥体或信号量不同,管道文件描述符可以通过应用程序主事件循环(如libevent)轻松处理。 只要写入PIPE_BUF或更少的字节(我的Linux上为4096),从不同线程写入同一个管道就是原子的。

下面是一个演示,创建10个线程,每个线程有不同的使用寿命。 然后主线程等待任何线程终止并打印其线程ID。 当所有十个线程都完成时它终止。

 $ cat test.cc #include <iostream> #include <pthread.h> #include <unistd.h> #include <stdlib.h> #include <time.h> void* thread_fun(void* arg) { // do something unsigned delay = rand() % 10; usleep(delay * 1000000); // notify termination int* thread_completed_fd = static_cast<int*>(arg); pthread_t thread_id = pthread_self(); if(sizeof thread_id != write(*thread_completed_fd, &thread_id, sizeof thread_id)) abort(); return 0; } int main() { int fd[2]; if(pipe(fd)) abort(); enum { THREADS = 10 }; time_t start = time(NULL); // start threads for(int n = THREADS; n--;) { pthread_t thread_id; if(pthread_create(&thread_id, NULL, thread_fun, fd + 1)) abort(); std::cout << time(NULL) - start << " sec: started thread " << thread_id << '\n'; } // wait for the threads to finish for(int n = THREADS; n--;) { pthread_t thread_id; if(sizeof thread_id != read(fd[0], &thread_id, sizeof thread_id)) abort(); if(pthread_join(thread_id, NULL)) // detached threads don't need this call abort(); std::cout << time(NULL) - start << " sec: thread " << thread_id << " has completed\n"; } close(fd[0]); close(fd[1]); } $ g++ -o test -pthread -Wall -Wextra -march=native test.cc $ ./test 0 sec: started thread 140672287479552 0 sec: started thread 140672278759168 0 sec: started thread 140672270038784 0 sec: started thread 140672261318400 0 sec: started thread 140672252598016 0 sec: started thread 140672243877632 0 sec: started thread 140672235157248 0 sec: started thread 140672226436864 0 sec: started thread 140672217716480 0 sec: started thread 140672208996096 1 sec: thread 140672208996096 has completed 2 sec: thread 140672226436864 has completed 3 sec: thread 140672287479552 has completed 3 sec: thread 140672243877632 has completed 5 sec: thread 140672252598016 has completed 5 sec: thread 140672261318400 has completed 6 sec: thread 140672278759168 has completed 6 sec: thread 140672235157248 has completed 7 sec: thread 140672270038784 has completed 9 sec: thread 140672217716480 has completed