【Linux】终止线程
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
为什么线程终止这么重要?
2. 一张图看懂线程的4种“死法”
3. 实战1:温柔派——pthread_exit()优雅退出
场景
代码示例
4. 实战2:暴力派——pthread_cancel()强制终止
场景
代码示例
关键点
5. 实战3:信号派——pthread_kill()精准打击
场景
代码示例
6. 实战4:自杀派——线程自己return
最简单粗暴的方式
7. 避坑指南:资源清理与死锁
必做:注册清理函数
一、
为什么线程终止这么重要?
想象一个场景:你的服务器有1000个线程在处理用户请求,突然某个线程陷入死循环,CPU飙到100%,怎么办?
-
粗暴kill进程? 会连累其他999个正常线程。
-
放任不管? 内存泄漏、句柄耗尽,最终系统崩溃。
结论: 必须学会精准、安全地终止单个线程。
2. 一张图看懂线程的4种“死法”
(下图来自课程课件,建议右键新标签页打开高清图)
https://example.com/thread_kill_methods.png
3. 实战1:温柔派——pthread_exit()
优雅退出
场景
线程完成任务后,主动通知主线程:“我干完了,可以收尸了”。
代码示例
#include <pthread.h>
#include <stdio.h>void* worker(void* arg) {printf("子线程:开始工作...\n");// 模拟耗时任务sleep(2);printf("子线程:任务完成,准备退出!\n");// 关键:优雅退出pthread_exit("线程结束啦");
}int main() {pthread_t tid;pthread_create(&tid, NULL, worker, NULL);void* retval;pthread_join(tid, &retval);printf("主线程收到消息:%s\n", (char*)retval);return 0;
}
4. 实战2:暴力派——pthread_cancel()
强制终止
场景
线程卡死在read()
或死循环,需要外部强制终止。
代码示例
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>void* stubborn_thread(void* arg) {printf("子线程:进入死循环...\n");while(1) {// 关键点:必须设置取消点!pthread_testcancel(); }return NULL;
}int main() {pthread_t tid;pthread_create(&tid, NULL, stubborn_thread, NULL);sleep(1);printf("主线程:强制终止子线程!\n");pthread_cancel(tid);pthread_join(tid, NULL);printf("子线程已终止\n");return 0;
}
关键点
-
pthread_cancel()
不是立即生效,需要线程遇到取消点(如pthread_testcancel()
、sleep()
、read()
等)。 -
可通过
pthread_setcancelstate()
控制是否允许被取消。
5. 实战3:信号派——pthread_kill()
精准打击
场景
只想终止线程,但不影响进程(注意:pthread_kill
不是杀死,而是发信号)。
代码示例
#include <pthread.h>
#include <signal.h>
#include <stdio.h>void* signal_handler_thread(void* arg) {printf("子线程:等待信号...\n");pause(); // 等待信号到来printf("子线程:收到信号,退出!\n");return NULL;
}int main() {pthread_t tid;pthread_create(&tid, NULL, signal_handler_thread, NULL);sleep(1);printf("主线程:发送SIGUSR1信号\n");pthread_kill(tid, SIGUSR1);pthread_join(tid, NULL);return 0;
}
6. 实战4:自杀派——线程自己return
最简单粗暴的方式
void* simple_exit(void* arg) {printf("线程直接return\n");return NULL; // 等价于pthread_exit(NULL)
}
7. 避坑指南:资源清理与死锁
必做:注册清理函数
void cleanup(void* arg) {printf("清理资源:关闭文件描述符%d\n", *(int*)arg);close(*(int*)arg);
}void* thread_with_resource(void* arg) {int fd = open("data.txt", O_RDONLY);pthread_cleanup_push(cleanup, &fd); // 注册清理函数// 模拟异常退出pthread_exit(NULL);pthread_cleanup_pop(0); // 不会执行到这里return NULL;
}