当前位置: 首页 > news >正文

【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;
}​

http://www.dtcms.com/a/361522.html

相关文章:

  • 旧物回收小程序:科技赋能,开启旧物新生之旅
  • 02-Media-1-acodec.py 使用G.711编码和解码音频的示例程序
  • 《投资-41》- 自然=》生物=》人类社会=》商业=》金融=》股市=》投资,其层层叠加构建中内在的相似的规律和规则
  • AR巡检系统:多源数据同步,开启工业智能化新纪元
  • 单链表的基本原理与实现
  • PyCharm 2025版本中新建python工程文件自动创建.venv的意义和作用
  • 【PCIE 系统】111 PCIE 设备 TYPE 0、TYPE 1
  • Google Gemini 2.5 Flash Image(Nano-Banana)震撼登场!人人都能免费用的AI修图神器!
  • 【开题答辩全过程】以 校园帮帮团跑腿系统的设计与实现为例,包含答辩的问题和答案
  • Leetcode 3664. Two-Letter Card Game
  • LeetCode 面试经典 150_滑动窗口_串联所有单词的子串(32_30_C++_困难)(滑动窗口:控制起点和滑动距离)
  • 原位表征技术在水系电池研究稳定性测试中的应用-测试GO
  • 教育 AI 的下半场:个性化学习路径生成背后,技术如何平衡效率与教育本质?
  • 学习日记-spring-day47-9.1
  • 使用LoadBalancer替换Ribbon(五)
  • 深入解析quiche开源项目:从QUIC协议到云原生实践
  • 每日算法题【二叉树】:计算二叉树节点的个数、叶子结点的个数、第k层节点的个数
  • 【面试场景题】不使用redis、zk如何自己开发一个分布式锁
  • 数据库索引失效的原因+示例
  • 视觉引导机械手双夹爪抓取:偏心旋转补偿与逆运动学求解
  • 卷积神经网络训练全攻略:从理论到实战
  • 【K8s】整体认识K8s之Configmap、Secret/ResourceQuota资源配额/访问控制
  • HTTP/2 多路复用
  • [C语言] 结构体 内存对齐规则 内存大小计算
  • 基于springboot生鲜交易系统源码和论文
  • 一文读懂k8s的pv与pvc原理
  • 威科夫与高频因子
  • 2.充分条件与必要条件
  • Android Framework打电话禁止播放运营商视频彩铃
  • Coze源码分析-工作空间-资源库-前端源码