C++20:std::stop_source让线程说停就停

发布时间:2026/11/14 18:22:30

C++20:std::stop_source让线程说停就停 std::stop_source是 C20 引入的标准库组件位于stop_token头文件中用于在多线程编程中实现协同式线程取消Cooperative Thread Cancellation。它提供了一种线程安全、优雅且通用的机制用来发起“停止请求”使运行中的异步任务或后台线程能够主动检查并安全退出。背景对比在 C20 之前终止线程通常依赖手动维护std::atomicbool标志位或者使用平台特定的 API如 POSIXpthread_cancel。然而平台强制终止极易导致 RAII 析构函数未运行、互斥锁死锁以及资源泄漏等未定义行为UB。核心协作三元组C20 的协同取消机制由三个相互协作的组件构成std::stop_source信号控制端负责发起停止信号调用.request_stop()。std::stop_token信号观察端传递给工作线程用于轮询或检查是否收到了停止信号调用.stop_requested()。std::stop_callback回调绑定机制允许注册回调函数当停止请求被发起时同步触发用于打断处于阻塞状态的 I/O 或条件变量。一、 API 详解1.std::stop_source核心接口核心控制与 Token 获取**request_stop()-bool**作用发起停止请求。返回值首次成功发起停止请求返回true若此前已发起过停止请求或当前对象未关联有效的底层状态返回false。副作用使所有关联的std::stop_token::stop_requested()返回true并同步触发所有已注册的std::stop_callback。**get_token()-std::stop_token**作用获取与当前stop_source绑定共享状态的std::stop_token对象用于下发给工作线程。状态查询**stop_requested() const-bool**作用检查关联的底层状态是否已收到停止请求。**stop_possible() const-bool**作用检查当前对象是否仍有可能发起停止请求。若关联了有效状态且未被全部释放返回true若为默认构造的空对象或所有关联的stop_source均已销毁返回false。生命周期与比较构造函数stop_source()默认构造创建一个新的可触发停止请求的底层共享状态。stop_source(std::nostopstate_t)构造一个不带底层状态的空对象stop_possible()为false。拷贝 / 移动构造支持拷贝与移动。由于底层使用引用计数管理状态拷贝出的多个stop_source共享同一个底层状态。**swap()/std::swap**交换两个stop_source对象的底层状态。比较运算符 (/!)判断两个stop_source是否共享同一个底层停止状态或均为空。2.std::stop_token核心接口状态查询**stop_requested() const-bool**作用检查关联的std::stop_source是否已发起停止请求。典型用途作为工作线程主循环的退出条件如while (!stoken.stop_requested())。**stop_possible() const-bool**作用检查当前token是否仍有可能收到停止请求。若关联了有效状态且至少存在一个存活的stop_source返回true若所有stop_source均已析构或token本身为无状态对象nostopstate返回false。优化场景在长循环中若stop_possible()为false可提前终止对stop_requested()的无效轮询。生命周期与比较构造函数stop_token()创建不包含底层状态的空 tokenstop_possible()和stop_requested()均返回false。拷贝与移动支持轻量级拷贝与移动多个stop_token可分发至多个并发线程共享同一个状态观察点。swap()与比较运算符 (/!)与stop_source行为一致比较或交换底层共享状态。3.std::stop_source与std::stop_token对比维度std::stop_sourcestd::stop_token角色定义信号控制者控制端信号观察者只读端核心职责发起停止请求request_stop()检查停止状态stop_requested()线程归属通常由主控线程 / 管理线程持有传递给一个或多个后台工作线程接口安全性拥有修改权可改变底层共享状态完全只读无法发起取消天然编译期接口安全生命周期依赖只要存在一个存活的stop_source即可触发取消即使所有stop_source均已析构stop_token仍可安全查询但stop_possible()会变为false二、 代码示例示例 1配合std::thread或异步任务手动控制#includeiostream#includethread#includechrono#includestop_tokenvoidworker(std::stop_token stoken){while(!stoken.stop_requested()){std::coutWorker running...\n;std::this_thread::sleep_for(std::chrono::milliseconds(500));}std::coutWorker received stop request, cleaning up and exiting.\n;}intmain(){std::stop_source source;// 将与其绑定的 stop_token 传给工作线程std::threadt(worker,source.get_token());std::this_thread::sleep_for(std::chrono::seconds(2));// 主线程发起停止请求std::coutMain thread requesting stop...\n;source.request_stop();t.join();return0;}示例 2与std::jthread深度集成自动感知与生命周期绑定C20 的std::jthread内部原生集成了std::stop_source。若可调用对象Task/Function的首个参数类型为std::stop_tokenstd::jthread会自动传入 token并在析构时自动触发request_stop()并执行join()#includeiostream#includethread#includechronovoidworker(std::stop_token stoken){while(!stoken.stop_requested()){std::coutWorking...\n;std::this_thread::sleep_for(std::chrono::milliseconds(300));}std::coutCleaning up...\n;}intmain(){{// t 析构时会自动调用 request_stop() 并 join()std::jthreadt(worker);std::this_thread::sleep_for(std::chrono::seconds(1));// 亦可显式手动发起t.request_stop();}// 超出作用域自动发起停止请求并阻塞等待线程结束return0;}三、 架构亮点与设计哲学1. 读写分离与权责对等Separation of Concerns接口设计严格区分了“控制端”与“执行端”控制端stop_source独占修改权执行端stop_token仅保留只读观察权。这种编译期强化的类型约束彻底杜绝了工作线程误触发取消信号的可能性显著降低了多线程代码的耦合度。2. 协同式安全与无锁高效设计协同非强制区别于 POSIXpthread_cancel等强制终止线程的危险做法该机制强制要求工作线程“主动响应”确保了栈展开Stack Unwinding与 RAII 资源释放的完整性。高效无锁实现底层共享状态建立在原子变量与引用计数之上拷贝与状态检查均无需显式加锁拥有极高的并发性能。3. 解决阻塞响应的“灵魂”std::stop_callback如果仅有轮询stop_requested()当线程处于阻塞如 sleep、网络 I/O、条件变量等待时将无法及时响应。std::stop_callback允许向stop_token注册回调一旦request_stop()被触发回调将立即被调用例如用于中断 Socket 或唤醒条件变量。C20 同步引入了std::condition_variable_any::wait(lock, stoken, pred)彻底解决了“条件变量阻塞等待与取消信号协同”的难题。四、 局限性与设计遗憾踩坑避雷指南1. 无法直接中断系统级/C API 阻塞stop_token本质上是语言层面的状态标记与回调通知机制无法做到操作系统内核级的信号中断Interrupted System Call。风险点若线程阻塞在未封装stop_callback的传统 POSIXread()/select()或 Win32 阻塞 API 中单纯查询stop_token无法唤醒线程。必须在stop_callback中手动执行shutdown(fd)或关闭 Handle 来强制打断。2. 回调函数的同步执行上下文与死锁陷阱极易踩坑stop_callback默认是在调用request_stop()的线程上下文中同步Synchronously执行的。死锁风险若调用request_stop()的线程持有互斥锁 A而stop_callback内部也尝试获取锁 A将直接引发死锁。性能抖动若注册的回调逻辑较为昂贵会直接阻塞调用request_stop()的主控线程。3. 缺乏树状/层级化取消支持Non-Hierarchical标准库的实现是扁平化Flat的。在复杂的任务调度或 Actor 模型中常见的“取消父任务自动取消所有子任务但取消子任务不影响父任务”的层级取消逻辑Hierarchical CancellationC20 原生机制并不支持需要结合图/树结构二次封装。4. 对传统std::condition_variable的兼容性限制由于历史包袱传统的std::condition_variable硬绑定了std::unique_lockstd::mutex。出于 ABI 兼容与性能考虑它无法直接配合stop_token使用。必须切换到通用性更强但开销略高的std::condition_variable_any。
延伸阅读

更多相关文章

2026/11/14 18:22:29

AI驱动的跨平台英语学习系统:用兴趣视频构建个性化学习闭环

这次我们来看一个打通插件、网站和手机APP的完整英语学习系统。它的核心思路不是让你背单词书,而是让你用自己真正喜欢的视频内容来学英语——通过AI技术实现视频内容提取、生词管理、听力练习、口语跟读和复习测试的全流程闭环。如果你厌倦了传统英语学习软件的固定…

2026/11/11 23:33:18

AI记忆卡项目:本地部署与测试指南,打造个性化智能助手

这次我们来看一个能自动收集工作进度的 AI 记忆卡项目。它瞄准的核心痛点很直接:日常工作中,我们经常需要向 AI 助手重复描述项目背景、任务进展和个人偏好,这个过程繁琐且低效。这个项目通过一张“记忆卡”,让 AI 能够自动、持续…

2026/11/11 11:25:51

维修工程师的示波器实战:11 为什么有些问题,一测反而消失了?

第十一篇:为什么有些问题,一测反而消失了? ——当你拿起示波器的那一刻,你已经改变了现场 凌晨一点半。 包装线再次毫无征兆地停机。 通讯超时、PLC报警、EtherCAT从站丢失……五秒后系统又自行恢复。 过程极短,却足以让整条产线瘫痪。 维修团队已连续奋战三天,故障只…

2026/11/14 18:22:23

安慧职教电工证多少钱官方回应学历不高也能报

安慧职教电工证多少钱官方回应学历不高也能报 学历不高怕报不上名?别慌,官方回应明确: 安慧职教电工证多少钱 的问题,其实和学历没太大关系。只要你是年满18周岁、身体健康、具备相应作业能力的人员,就能参加电工证考试,不论你是初中、高中还是大专…

2026/11/14 18:22:23

徐工特种工程招聘,证书过期了怎么处理?这个证值不值得考?

徐工特种工程招聘,证书过期了怎么处理?这个证值不值得考? 证书过期了不知道怎么复审延期,这事儿别急,咱们今天就来聊聊【徐工特种工程招聘】相关的问题,特别是那些正在为证书复审犯愁的同行们,别再被这些问题绊住了手脚。证书是咱们特种作业从业者的“…

2026/11/14 18:22:23

电工证刚下来是几级通过率揭秘别再怕学历不高报不上名

电工证刚下来是几级通过率揭秘别再怕学历不高报不上名 学历不高怕报不上名?电工证刚下来是几级,这事儿别慌!别再被那些“学历门槛高”的谣言吓退了,真实情况是,只要符合报考条件, 学历不是限制因素…

2026/11/14 18:22:23

唐山哪里可以考电工证内部消息曝光,这些坑别再踩

唐山哪里可以考电工证内部消息曝光,这些坑别再踩 你是不是也这样?拿着报名表不知道该找哪个机构,担心被中介坑,花了钱还没证?别急,我来告诉你 唐山哪里可以考电工证 的内部消息,帮你避开那些看不见的坑。 为什么电工证在唐山这么火?…

2026/11/14 18:22:23

电工证还出证书吗?开封建筑工人考证避坑指南

电工证还出证书吗?开封建筑工人考证避坑指南 之前考的证在外省能不能转过来?这是很多在开封工作的建筑工人最关心的问题。尤其对于已经在外地考过电工证的工友来说,现在回到本地, 上岗必备…

2026/11/14 18:17:23

宁波特种车辆徐工集团怎么选?外省证书能转电子证书吗?

宁波特种车辆徐工集团怎么选?外省证书能转电子证书吗? 之前考的证在外省能不能转过来?这几乎是每个想在宁波特种车辆徐工集团从事相关工作的人都会问的问题。尤其现在电子证书开始普及,不少人担心之前在外地考的证能不能顺利在宁波使用,甚至是否还能转换…

2026/11/13 22:33:32

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/14 0:06:39

土木特种工考证官方报名入口怎么找 之前考的证在外省能不能转过来

土木特种工考证官方报名入口怎么找 之前考的证在外省能不能转过来 之前考的证在外省能不能转过来?这个问题我太熟悉了,作为一名干了十几年的特种作业证书办理从业者,每年都会遇到不少像你一样在外地考了证,回来却发现无法直接使用的学员。别急,今天我就…

2026/11/14 0:06:39

电工证要多久多钱保姆级教程:工地太忙根本没时间复习考试

电工证要多久多钱保姆级教程:工地太忙根本没时间复习考试 工地太忙根本没时间复习考试,你不是一个人。在信阳浉河区,很多刚进入工地的电工都面临这样的困境:工作强度大,时间碎片化,根本没有系统复习考试的机会。但电工证是上岗的硬门槛,…

2026/11/13 22:32:11

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/13 12:14:39

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑