main()中的poll()等待来自另一个应用程序的某种触发器,当有触发器时,pollHandler()被执行。在pollHandler()中,我希望根据轮询消息中的请求数启动'n'个线程。
但是现在在pollHandler()中,当我想在不同的for循环中使用pthread_join时,我无法访问thread_ids。我可以创建一个pthread id数组,并在循环块之外使用它,pthread_create和pthread_join都可以访问,但是poll()函数是活动的,它可以一次又一次地被调用,从而覆盖线程id。我如何保持这里的整洁-等待每个线程完成并为更多线程腾出空间?
int pollHandler(){
int num_req = poll.size();
for(int i=0; i < num_req; i++){
// start thread for each req
pthread_t tid;
// thread paramters dynamically allocated and freed later
struct parameters *p = (struct parameters*)malloc(sizeof(struct parameters));
if((pthread_create(&tid, NULL, thread_func, p) != 0){
return -1;
}
}
for(int i=0; i < num_req; i++){
// pthread_join here but no access to thread ids?
}
return 0;
}
int main(){
......
while(1){
poll(); //waits for a trigger from another application
}
}
我想根据轮询消息中的请求数启动'n'个线程数。
这种设计从根本上是有缺陷的:如果你得到一个请求(比如说)有10,000个请求,你不太可能能够创建一个单独的线程来处理每个请求,即使你可以,线程的创建和销毁也是低效的,最好避免。
一个更好的设计是启动一个线程池,并将工作分派给它们,等待所有工作完成后再返回,就像Martin James建议的那样。
也就是说,以下是实现当前设计的正确方法(为了清晰起见,省略了错误检查):
int pollHandler(){
int num_req = poll.size();
pthread_t *tids = calloc(num_req * sizeof(pthread_t));
for(int i=0; i < num_req; i++){
// start thread for each req
// thread paramters dynamically allocated and freed later
struct parameters *p = (struct parameters*)malloc(sizeof(struct parameters));
if((pthread_create(&tid[i], NULL, thread_func, p) != 0){
// bug here.
return -1;
}
}
for(int i=0; i < num_req; i++){
pthread_join(tids[i], NULL);
}
free(tids);
return 0;
我可以创建一个pthread id数组,并在for循环块之外使用它,pthread_create和pthread_join都可以访问,但是poll()函数是活动的,它可以一次又一次地被调用,从而覆盖线程id。
除非pollHandler()
可以中断另一个pollHandler()
,否则它在前一个调用完成之前不会被调用,因此上面的代码是"安全的"。
如果pollHandler()
可以作为中断的一部分运行,那么你的代码已经无可希望地破碎了(malloc
和pthread_create
都不是异步信号安全的,因此不能在信号处理程序中调用)。
注://bug here
怎么了?
你不能只是返回那里——你需要连接你已经创建的线程。您还需要在那里设置free(tids);
。