2026/2/10 0:11:11
网站建设
项目流程
网站正在维护中,网站seo,网站模板对seo的影响吗,网站打开是404错误代码在 Linux 多线程编程中#xff0c;经常遇到 “主线程需要主动终止子线程执行” 的场景 —— 比如子线程处理任务超时、业务逻辑需要中断工作线程#xff0c;这时线程取消#xff08;pthread_cancel#xff09;就是核心解决方案#xff01;本文整理线程取消的核心概念、关键…在 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取消点时响应取消终止执行。五、踩坑取消状态设为 DISABLE 时发送请求取消请求会被忽略线程继续执行直到正常退出延迟取消无取消点若线程执行无取消点的死循环如while(1);即使发送取消请求也无法终止未调用 pthread_join 回收资源发送取消请求后线程终止但资源未回收产生僵尸线程立即取消ASYNCHRONOUS的风险线程可能在任意时刻终止易导致资源泄漏如未释放 malloc 的内存、未关闭文件描述符忽略接口返回值未校验 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 多线程 “协商式终止” 的核心机制核心要点取消请求是 “通知”目标线程需配置ENABLE状态才会响应延迟取消DEFERRED是安全选择仅在取消点响应便于资源清理立即取消ASYNCHRONOUS慎用易导致资源泄漏发送取消请求后必须通过pthread_join回收线程资源。对比 “共享变量终止线程”需线程主动检查变量线程取消更高效但需注意资源清理是多线程按需终止的必备知识点。