news 2026/10/18 16:38:22

Linux 线程编程 - 线程取消:取消状态 + 取消类型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux 线程编程 - 线程取消:取消状态 + 取消类型

在 Linux 多线程编程中,经常遇到 “主线程需要主动终止子线程执行” 的场景 —— 比如子线程处理任务超时、业务逻辑需要中断工作线程,这时线程取消(pthread_cancel)就是核心解决方案!本文整理线程取消的核心概念、关键接口和实战代码,零基础也能看懂。

一、核心特点

1. 适用场景

  • 主线程需要主动终止子线程执行(如超时任务终止、批量线程按需停止);
  • 线程执行耗时操作时,需响应外部终止指令;
  • 替代 “暴力杀死线程” 的方式,实现 “协商式” 线程终止。

2. 核心逻辑

线程取消是 “通知式” 操作,而非 “强制杀死”,目标线程的执行逻辑由两个核心属性决定:

核心属性作用可选值
取消状态决定是否接收取消请求① PTHREAD_CANCEL_ENABLE(默认,允许接收)② PTHREAD_CANCEL_DISABLE(拒绝接收)
取消类型决定接收请求后何时终止① PTHREAD_CANCEL_DEFERRED(默认,延迟取消,需执行到 “取消点” 才终止)② PTHREAD_CANCEL_ASYNCHRONOUS(立即取消,收到请求后马上终止)

关键概念:取消点系统预定义的 “触发取消” 的函数,延迟取消(DEFERRED)仅在执行这些函数时响应取消请求,常见取消点:pthread_join、pthread_cond_wait、sem_wait、sleep、read、write等(大部分阻塞型系统调用)。

二、关键接口

接口功能关键说明
pthread_setcancelstate设置线程取消状态参数 1:新状态(ENABLE/DISABLE);参数 2:存储旧状态(可传 NULL);成功返回 0,失败返回错误码
pthread_setcanceltype设置线程取消类型参数 1:新类型(DEFERRED/ASYNCHRONOUS);参数 2:存储旧类型(可传 NULL);成功返回 0,失败返回错误码
pthread_cancel向目标线程发送取消请求参数:目标线程 ID;仅发送请求,不等待线程终止;成功返回 0,失败返回错误码
pthread_join等待线程终止并回收资源发送取消请求后,需通过该接口回收线程资源,避免僵尸线程

三、实战代码

模拟场景:主线程创建子线程后,等待 5 秒发送取消请求,子线程设置 “允许取消 + 延迟取消”,执行循环任务并响应取消请求:

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> void* thread_function(void* arg) { // 1. 设置取消状态:允许接收取消请求 int res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); if (res != 0) { perror("Thread pthread_setcancelstate failed"); exit(1); } // 2. 设置取消类型:延迟取消(默认,可省略,此处显式配置) res = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); if (res != 0) { perror("Thread pthread_setcanceltype failed"); exit(1); } printf("thread_function is running\n"); // 循环执行任务(sleep是取消点,触发延迟取消) for (int i = 0; i < 10; i++) { printf("Thread is still running (%d)...\n", i); sleep(1); // 取消点:执行到此处时响应取消请求 } // 若未被取消,正常退出 pthread_exit(0); } int main() { // 1. 创建子线程 pthread_t a_thread; int res = pthread_create(&a_thread, NULL, thread_function, NULL); if (res != 0) { perror("Thread creation failed"); exit(1); } // 2. 主线程等待5秒,模拟业务逻辑后发送取消请求 sleep(5); printf("Canceling thread...\n"); res = pthread_cancel(a_thread); if (res != 0) { perror("Thread cancelation failed"); exit(1); } // 3. 等待子线程终止并回收资源 printf("Waiting for thread to finish...\n"); void* thread_result; res = pthread_join(a_thread, &thread_result); if (res != 0) { perror("Thread join failed"); exit(1); } printf("Thread canceled successfully\n"); return 0; }

四、编译运行

线程取消依赖 pthread 库,编译时必须加-lpthread:

# 编译代码 gcc thread_cancel.c -o thread_cancel -lpthread # 运行程序 ./thread_cancel

运行结果说明

thread_function is running Thread is still running (0)... Thread is still running (1)... Thread is still running (2)... Thread is still running (3)... Thread is still running (4)... Canceling thread... Waiting for thread to finish... Thread canceled successfully

子线程执行 5 次循环后,主线程发送取消请求,子线程在第 5 次 sleep(取消点)时响应取消,终止执行。

五、踩坑

  1. 取消状态设为 DISABLE 时发送请求:取消请求会被忽略,线程继续执行直到正常退出;
  2. 延迟取消无取消点:若线程执行无取消点的死循环(如while(1);),即使发送取消请求也无法终止;
  3. 未调用 pthread_join 回收资源:发送取消请求后,线程终止但资源未回收,产生僵尸线程;
  4. 立即取消(ASYNCHRONOUS)的风险:线程可能在任意时刻终止,易导致资源泄漏(如未释放 malloc 的内存、未关闭文件描述符);
  5. 忽略接口返回值:未校验 pthread_setcancelstate/type 的返回值,配置失败后无感知,线程行为不符合预期。

六、进阶扩展

1. 自定义取消点

若线程执行无系统取消点的逻辑(如纯计算循环),可通过pthread_testcancel()手动插入取消点:

// 子线程循环中插入自定义取消点 for (int i = 0; i < 1000000; i++) { // 纯计算逻辑,无系统取消点 int x = i * i; pthread_testcancel(); // 手动取消点:检查是否有取消请求,有则终止 }

2. 安全取消:清理资源

线程被取消前,可通过pthread_cleanup_push/pop注册清理函数,确保资源释放:

// 清理函数:释放资源 void cleanup_handler(void* arg) { printf("Cleaning up resources...\n"); free(arg); // 释放malloc的内存 } void* thread_function(void* arg) { char* buf = malloc(1024); // 注册清理函数(需成对使用push/pop) pthread_cleanup_push(cleanup_handler, buf); // 业务逻辑... sleep(1); // 注销清理函数(即使被取消,也会执行) pthread_cleanup_pop(1); // 参数1:执行清理函数;0:不执行 pthread_exit(0); }

七、总结

线程取消是 Linux 多线程 “协商式终止” 的核心机制,核心要点:

  1. 取消请求是 “通知”,目标线程需配置ENABLE状态才会响应;
  2. 延迟取消(DEFERRED)是安全选择,仅在取消点响应,便于资源清理;
  3. 立即取消(ASYNCHRONOUS)慎用,易导致资源泄漏;
  4. 发送取消请求后,必须通过pthread_join回收线程资源。

对比 “共享变量终止线程”(需线程主动检查变量),线程取消更高效,但需注意资源清理,是多线程按需终止的必备知识点。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 18:13:01

Qwen3-VL辅助开发ComfyUI自定义节点工作流

Qwen3-VL辅助开发ComfyUI自定义节点工作流 在AI图像生成工具日益普及的今天&#xff0c;开发者们面临一个现实矛盾&#xff1a;一方面&#xff0c;像 ComfyUI 这样的节点式工作流系统提供了无与伦比的灵活性和可复现性&#xff1b;另一方面&#xff0c;其高度依赖手动配置、代码…

作者头像 李华
网站建设 2026/10/17 22:22:33

Qwen3-VL空间感知升级:精准判断物体遮挡与3D位置关系

Qwen3-VL空间感知升级&#xff1a;精准判断物体遮挡与3D位置关系 在自动驾驶系统试图识别前方车辆时&#xff0c;如果仅依赖“图像中有个汽车”这样的信息&#xff0c;显然远远不够——真正决定是否刹车或变道的关键是&#xff1a;“这辆车离我有多远&#xff1f;”“它是否被其…

作者头像 李华
网站建设 2026/10/13 23:49:20

AI应用架构师的技术支持:AI驱动组织优化的工具选择

AI应用架构师的技术支持&#xff1a;AI驱动组织优化的工具选择 一、引言&#xff1a;AI驱动组织优化的“落地困境” 某零售企业的CIO曾向我抱怨&#xff1a;“我们花了500万买了AI平台&#xff0c;结果一年下来只做了个客户画像demo——业务部门说‘用起来麻烦’&#xff0c;技…

作者头像 李华
网站建设 2026/10/15 3:51:44

Qwen3-VL支持多语言混合OCR,中文英文无缝切换

Qwen3-VL 支持多语言混合 OCR&#xff0c;中文英文无缝切换 在智能文档处理日益普及的今天&#xff0c;一张照片里同时出现中英文内容早已司空见惯&#xff1a;产品说明书上的技术参数夹杂着英文缩写&#xff0c;跨国合同中的条款混排双语表述&#xff0c;甚至一张餐厅菜单也可…

作者头像 李华
网站建设 2026/10/15 7:24:45

Keil5中文输入显示乱?项目应用前的基础设置

Keil5中文输入乱码&#xff1f;别急&#xff0c;一文讲透根源与实战配置你有没有遇到过这样的场景&#xff1a;在Keil Vision里写注释&#xff0c;刚打下“// 初始化GPIO”&#xff0c;再一看——变成了??GPIO&#xff1f;或者打开同事传来的工程文件&#xff0c;所有中文注释…

作者头像 李华
网站建设 2026/10/18 8:39:27

房地产营销变革:Sonic生成楼盘讲解数字人视频

房地产营销变革&#xff1a;Sonic生成楼盘讲解数字人视频 在房地产销售一线&#xff0c;你是否遇到过这样的场景&#xff1f;客户深夜打开官网想了解某个新盘的户型细节&#xff0c;却发现只有冷冰冰的文字和图片&#xff1b;售楼处高峰期人满为患&#xff0c;销售顾问连喝口水…

作者头像 李华