如何无需等待pthread_barrier_wait()返回就调用pthread_barrier_destroy()
关于pthread_barrier_destroy挂起问题的解决方案
你遇到的挂起问题完全符合POSIX线程规范的约定:
pthread_barrier_destroy被调用时如果仍有线程阻塞在pthread_barrier_wait调用上,行为是未定义的,大部分实现会直接挂起等待所有wait调用返回。
方案1:配合pthread_join使用线程取消(适配现有代码的最小改法)
你现在的代码只发送了取消信号,没有等待线程实际退出就直接销毁屏障,是核心问题。pthread_cancel只是向线程发送取消请求,不会等待线程终止,此时线程可能还停留在pthread_barrier_wait的阻塞状态。
修改方法非常简单,在发送取消请求后加一段pthread_join逻辑,等待所有工作线程完全回收后再销毁屏障:
for(int i=0;i<p; i++){ printf("Thread %lu completed in %d passes\n",threads[i],find_tstat(threads[i])->count); pthread_cancel(threads[i]); } // 新增:等待所有线程完全退出,确保没有残留的barrier_wait调用 for(int i=0;i<p; i++){ pthread_join(threads[i], NULL); } // 此时再销毁屏障不会出现挂起 pthread_barrier_destroy(&your_barrier); printf("================================================================\n"); return a;
注意:pthread_barrier_wait属于标准取消点,阻塞在该调用上的线程收到取消信号后会立即退出,不会残留阻塞状态
方案2:使用退出标志位的优雅退出方案(更推荐,无取消风险)
线程取消存在诸多隐式风险(比如线程持有互斥锁/内存资源时被取消,导致资源泄漏/死锁),更推荐用标志位控制线程正常退出,不需要用到取消逻辑:
- 定义全局退出标志:
volatile int exit_flag = 0;
- 工作线程逻辑中每次完成barrier等待后检查标志位:
void* worker_routine(void* arg) { while(1) { // 你的计算逻辑 int wait_res = pthread_barrier_wait(&your_barrier); // 屏障等待完成后检查退出标志 if (exit_flag) { break; } // 你的后续计算逻辑 } return NULL; }
- 主线程退出逻辑:
for(int i=0;i<p; i++){ printf("Thread %lu completed in %d passes\n",threads[i],find_tstat(threads[i])->count); } // 标记退出标志 exit_flag = 1; // 等待所有线程正常退出 for(int i=0;i<p; i++){ pthread_join(threads[i], NULL); } pthread_barrier_destroy(&your_barrier); printf("================================================================\n"); return a;
关键说明
不存在“还有未返回的wait调用时直接正常销毁barrier”的合法用法,所有符合POSIX标准的实现都要求销毁屏障前必须保证没有线程在操作该屏障,上述两种方案都是通过先回收线程的方式满足这个前提。
内容的提问来源于stack exchange,提问作者e god
相关产品推荐
相关产品推荐

