pthread多线程单线程出错时终止另一线程并优雅退出进程的实现方法
实现方案
核心原则:不要直接用pthread_cancel强制终止线程,除非你明确知道线程所有取消点、且做好了资源清理,否则容易出现内存泄漏、锁未释放等问题,优先用主动退出机制。
具体实现步骤
- 第一步:定义共享的全局状态变量,推荐用C11原子变量无需额外加锁,避免竞态问题:
#include <stdatomic.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h> pthread_t thr1, thr2; atomic_bool g_need_exit = false; // 全局退出标记
如果你使用的编译环境不支持C11原子变量,可以替换为普通bool变量,搭配
pthread_mutex_t互斥锁做读写保护即可。
- 第二步:修改线程函数逻辑,新增退出标记检查和出错标记逻辑:
void *func1(void *args) { while(1){ // 每次循环先检查是否需要主动退出 if (atomic_load(&g_need_exit)) { // 此处先释放当前线程持有的私有资源:malloc内存、打开的文件、持有的锁等 return (void *)0; } // 原有业务逻辑 // ..... if(/*error*/) { // 自身出错,设置全局退出标记,通知另一个线程主动退出 atomic_store(&g_need_exit, true); return (void *)-1; } } return (void *)0; } // func2逻辑和func1完全一致,同样添加退出标记检查逻辑即可 void *func2(void *args) { while(1){ if (atomic_load(&g_need_exit)) { // 释放当前线程私有资源 return (void *)0; } // 原有业务逻辑 // ..... if(/*error*/) { atomic_store(&g_need_exit, true); return (void *)-1; } } return (void *)0; }
- 第三步:修改主线程逻辑,轮询检测线程退出状态,出错时等待另一个线程主动退出后再终止进程:
int main(){ void *ret1, *ret2; if(pthread_create(&thr1, NULL, func1, NULL) != 0) { return -1; } if(pthread_create(&thr2, NULL, func2, NULL) != 0) { return -1; } // 轮询检查两个线程的退出状态 while (1) { // 检查线程1是否退出 if (pthread_tryjoin_np(thr1, &ret1) == 0) { if (ret1 == (void *)-1) { // 线程1出错,通知线程2退出 atomic_store(&g_need_exit, true); // 等待线程2完成资源释放后退出 pthread_join(thr2, &ret2); // 全局资源清理后退出进程 exit(EXIT_FAILURE); } // 线程1正常退出,等待线程2结束 pthread_join(thr2, &ret2); break; } // 检查线程2是否退出 if (pthread_tryjoin_np(thr2, &ret2) == 0) { if (ret2 == (void *)-1) { atomic_store(&g_need_exit, true); pthread_join(thr1, &ret1); exit(EXIT_FAILURE); } // 线程2正常退出,等待线程1结束 pthread_join(thr1, &ret1); break; } // 避免空转占用CPU,休眠1ms usleep(1000); } return 0; }
特殊场景说明
如果业务逻辑必须使用强制终止线程的方案,一定要配套pthread_cleanup_push/pthread_cleanup_pop注册线程清理函数,在线程被取消时自动释放资源、释放锁,同时要确认线程逻辑中存在取消点,避免终止请求不生效,非必要不推荐使用强制终止方案。
内容的提问来源于stack exchange,提问作者bvj0412
相关产品推荐
相关产品推荐

