发布时间:2026/8/8 8:15:09
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/8/8 8:15:09

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

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

2026/8/8 8:15:09

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

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

2026/8/8 8:15:09

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

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

2026/8/8 9:20:12

AI会不会乱来?为什么转账这种事永远轮不到AI拍板

AI会不会乱来?为什么转账这种事永远轮不到AI拍板 去银行办过大额转账的老板,都见过这个场面:柜员把单子敲完,不能直接放款,得举手叫主管,主管走过来刷卡、看单、再按一次确认,钱才出得去。银行的…

2026/8/8 9:20:12

I2S、PCM与TDM音频接口协议详解:从立体声到多通道传输

1. 项目概述:从音频接口的“通用语”说起 搞嵌入式音频开发,或者玩过树莓派、ESP32这类板子做音频项目的老铁,肯定绕不开I2S、PCM这几个词。它们不像I2C、SPI那样家喻户晓,但在数字音频的世界里,却是设备之间“对话”的…

2026/8/8 9:20:12

MCP协议:AI Agent万能工具箱,打破语言与进程壁垒

1. 项目概述:为什么我们需要一个“万能工具箱”?如果你最近在折腾AI Agent,尤其是想让你的Agent去调用一些外部工具——比如查个天气、读个本地文件、或者控制一下智能家居——那你大概率已经踩过几个坑了。最常见的场景是:你用Py…

2026/8/8 9:20:12

CX3 USB 3.0 UVC摄像头固件开发与调试全攻略

1. 项目缘起:为什么我要啃这块“硬骨头”? 最近在搞一个嵌入式视觉项目,核心是使用Cypress(现英飞凌)的CX3 USB 3.0控制器,来实现一个高速的UVC(USB Video Class)摄像头。说实话&…

2026/8/8 9:20:12

文献太多看不完怎么办?先筛选再精读的办法

当文献数量过多之际, 切莫自第一篇起始逐字逐句地阅读。首先围绕研究问题设定纳入标准并开展去重工作, 接着运用标题、摘要、全文进行三级筛选;对于保留下来的文献依据“核心证据、方法参考、背景材料”予以分级。在进行精读之时, 仅仅阅读与你当下任务存在关联的部…

2026/8/8 9:15:12

智慧树刷课插件:3步配置实现视频自动化学习的完整指南

智慧树刷课插件:3步配置实现视频自动化学习的完整指南 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 你是否曾经花费大量时间在智慧树平台上手动点击"…

2026/8/7 19:43:11

如何用免费工具突破游戏窗口限制:SRWE完整使用指南

如何用免费工具突破游戏窗口限制:SRWE完整使用指南 【免费下载链接】SRWE Simple Runtime Window Editor 项目地址: https://gitcode.com/gh_mirrors/sr/SRWE 你是否遇到过这样的困扰?想为心爱的游戏截图,却发现游戏不支持自定义分辨率…

2026/8/8 0:04:22

Java图像处理实战指南

要执行这些 Java AWT 图像处理程序,你需要将它们分别保存为独立的 .java 文件,并使用 javac 编译,然后使用 java 运行。以下是每个程序的核心执行步骤、依赖关系和要点。 通用执行步骤 保存文件:将每个 listing 的代码复制到文本…

2026/8/8 0:04:23

昇腾AI代理实现多号通话自动化

基于昇腾(Ascend)硬件与AtomGit AI社区的开源生态,结合AI Agent技术,可以实现一个模拟“通话重复使用机号复制”功能的安卓手机应用原型。其核心是利用AI Agent进行意图理解、任务编排和自动化操作,模拟或管理多号码的…

2026/8/8 0:04:23

2026年Graph+AI Agents最新创新思路

本次围绕GraphAI Agents这个方向筛选了15篇高质量论文,都是近年来具有较高引用价值或方法创新的研究工作,其中部分来自IJCAI、AAAI、ICRA。 对于论文er来说,这些论文方法结构清晰、可复现性较强,在多个任务上都有可延展的空间。如…

2026/8/7 9:44:18

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/7 19:03:32

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/8 2:17:42

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…