pthread_join() 用于未知数量的线程
Posted
技术标签:
【中文标题】pthread_join() 用于未知数量的线程【英文标题】:pthread_join() for unknown number of threads 【发布时间】:2021-12-05 02:05:00 【问题描述】:main() 中的 poll() 等待来自另一个应用程序的某种触发器,当有触发器时,执行 pollHandler()。在 pollHandler() 中,我想根据轮询消息中的请求数启动“n”个线程。
但是现在在 pollHandler() 中,当我想在不同的 for 循环中使用 pthread_join 时,我无法访问 thread_ids。我可以创建一个 pthread id 数组并在 pthread_create 和 pthread_join 都可以访问的 for 循环块之外使用它,但是 poll() 函数是活动的,它可以一次又一次地被调用,从而覆盖线程身份证。我如何在这里保持清洁 - 等待每个线程完成并腾出空间来拥有更多线程?
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
【问题讨论】:
所以你问如何扩展一个数组?realloc
但是你需要清理线程或者有资源耗尽的风险。所以你可能需要一些更复杂的东西。您可能需要某种由线程 ID 键入的关联数组,以便您可以从“中间”删除条目。而且您需要能够在轮询时检测到线程结束。 (或者至少在创建更多线程之前检查哪些线程不再运行)。
未知的线程数?!?!谁在你的进程中跑来跑去并在你不知情的情况下创建线程?
用线程池重新设计 - 创建一个生产者/消费者队列并挂起 128 'while(true)read_queue;程序启动后,process message 立即将其线程化。不要再创建任何线程,也不要尝试终止任何线程。没有加入,没有线程ID,没有线程微管理,没问题。 pthread_join() 很可怕,一出生就扼杀了许多尝试的多线程应用程序:(
@ikegami 谢谢
【参考方案1】:
我想根据轮询消息中的请求数启动“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 数组并在 pthread_create 和 pthread_join 都可以访问的 for 循环块之外使用它,但是 poll() 函数是活动的,它可以被一次又一次地调用,从而覆盖线程 id。
除非pollHandler()
可以中断另一个pollHandler()
,否则它不会在之前的调用完成之前被调用,所以上面的代码是“安全的”。
如果pollHandler()
可以作为中断的一部分运行,那么您的代码已经无可救药地被破坏了(malloc
和pthread_create
都不是异步信号安全的,因此不能在信号处理程序中调用)。
附: //bug here
怎么了?
您不能只返回那里 - 您需要加入您已经创建的线程。您还需要在那里free(tids);
。
【讨论】:
谢谢。你是对的,线程数应该有一个上限。另外,pollHandler() 可以被另一个 pollHandler() 打断,所以也许我需要先看看改变这部分设计? 此处有错误,因为我无法访问 pthread_join 的另一个 for 循环中的 thread_id。 @bvj0412 "pollHandler()
可以被打断" -- 你确定吗?被什么打断了?以上是关于pthread_join() 用于未知数量的线程的主要内容,如果未能解决你的问题,请参考以下文章
是否可以在没有 pthread_join() 的情况下使用 pthread?