std::stop_token是C++20引入的轻量级只读停止信号,用于让工作函数非阻塞、可响应、无竞态地检查退出请求;它需配合std::jthread或手动stop_source使用,不能强制终止线程,仅提供协作式取消通知机制。

std::stop_token 是什么,它能解决什么问题
std::stop_token 本身不“关闭”线程,它只是传递一个轻量级、只读的停止请求信号。真正起作用的是 std::jthread(C++20 引入)在析构时自动调用 request_stop(),或者你手动调用 stop_source::request_stop()。它的价值在于让工作函数能**非阻塞、可响应、无竞态地检查是否该退出**——避免用 volatile bool + sleep 轮询,也绕开 pthread_cancel 这类危险操作。
怎么写一个可被 stop_token 中断的循环
核心是把 stop_token 传入工作函数,并在循环中用 token.stop_requested() 检查(注意:不是每次都要查,尤其在阻塞点之后)。常见错误是只在循环开头查一次,导致阻塞调用(如 std::this_thread::sleep_for)无法及时响应。
- 推荐模式:在每次可能长时间执行前检查,尤其是进入阻塞调用前
- 阻塞调用本身支持 stop_token 的(如
std::condition_variable::wait的重载)应优先使用,它们会自动响应并抛出std::stop_token-related exception - 若用
std::this_thread::sleep_for,必须配合token.stop_requested()手动轮询,且建议用短超时(如 10ms),否则响应延迟高
示例:
void worker(std::stop_token token) {
while (!token.stop_requested()) {
do_work();
// 避免长 sleep;改用带超时的 wait 或短 sleep + 检查
std::this_thread::sleep_for(10ms);
}
}
为什么不能直接用 std::thread + 自己管理 stop_source
std::thread 不自带停止机制,你需要自己声明 std::stop_source、传 stop_token、并在适当时候调用 request_stop(),还必须确保 stop_source 生命周期覆盖整个线程运行期。容易出错的地方有:
立即学习“C++免费学习笔记(深入)”;
-
stop_source在线程启动前就销毁 →token.stop_requested()永远返回 false - 忘记调用
join()或detach()→ 程序终止时std::thread析构抛异常 - 多个线程共用一个
stop_source但没同步 → 竞态修改状态
而 std::jthread 把这些全包了:构造时绑定 stop_source,析构时自动 request_stop() 并 join(),代码更简洁、更安全。
std::jthread 析构时 request_stop() 的时机很关键
std::jthread 析构时会先调用 request_stop(),再调用 join()。这意味着:如果工作函数还在运行,它有机会在 join() 阻塞前看到 stop_requested() 并主动退出。但如果你的工作函数卡在不可中断的系统调用里(比如没封装 stop_token 的 read() 或 accept()),join() 就会一直等下去——这不是 std::jthread 的缺陷,而是底层 API 本身不支持协作式取消。
此时必须换用支持取消的封装(如基于 epoll + eventfd 的自定义 wait,或用 std::condition_variable 配合 notify_all() 唤醒),或者给系统调用加超时并手动检查 token。
别指望 std::stop_token 能强制杀掉线程;它只负责“通知”,不负责“终止”。真正的优雅退出,取决于你工作函数里每一步是否对停止信号做了响应。


















