C++20标准新增的std::stop_token是一套用于线程协作停止的标准化工具,它解决了传统线程停止方案中需要手动管理停止状态、容易出现竞态条件的问题,让线程停止逻辑更加安全和规范。

std::stop_token核心组件介绍
std::stop_token的协作停止机制由三个核心类组成,三者配合实现完整的停止流程:
- std::stop_token:停止令牌,线程执行函数可以通过它查询是否收到了停止请求,是被动接收停止信号的角色。
- std::stop_source:停止源,用于主动发起停止请求,调用其request_stop()方法后会通知所有关联的stop_token。
- std::stop_callback:停止回调,当关联的stop_token收到停止请求时,会自动执行预先注册的回调函数,用于处理停止时的清理逻辑。
需要注意的是,stop_source和stop_token之间是关联的,一个stop_source可以生成多个stop_token,所有关联的token都会收到同一个stop_source发起的停止请求。
基础使用示例
下面是一个最简单的使用std::stop_token停止线程的示例,线程会循环检查停止状态,收到停止请求后主动退出:
#include <iostream>
#include <thread>
#include <stop_token>
#include <chrono>
// 线程执行函数,接收stop_token作为参数
void worker_func(std::stop_token st) {
int count = 0;
// 循环检查是否收到停止请求
while (!st.stop_requested()) {
std::cout << "线程运行中,计数: " << count++ << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "收到停止请求,线程退出" << std::endl;
}
int main() {
// 创建stop_source,用于发起停止请求
std::stop_source ssrc;
// 获取关联的stop_token,传入线程函数
std::stop_token st = ssrc.get_token();
std::thread t(worker_func, st);
// 主线程等待3秒后发起停止请求
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "主线程发起停止请求" << std::endl;
ssrc.request_stop();
t.join();
return 0;
}
运行上述代码可以看到,线程运行3次后收到停止请求,主动退出循环并结束执行,整个过程没有使用额外的共享变量,停止状态的管理由标准库自动完成。
使用std::stop_callback处理清理逻辑
如果线程在收到停止请求时需要执行特定的清理操作,比如释放资源、保存状态等,可以使用std::stop_callback注册回调函数,回调会在停止请求发起时自动执行:
#include <iostream>
#include <thread>
#include <stop_token>
#include <chrono>
void worker_with_callback(std::stop_token st) {
// 注册停止回调,当收到停止请求时执行
std::stop_callback cb(st, []() {
std::cout << "执行停止回调:释放资源、保存临时数据" << std::endl;
});
int count = 0;
while (!st.stop_requested()) {
std::cout << "线程运行中,计数: " << count++ << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "线程主逻辑退出" << std::endl;
}
int main() {
std::stop_source ssrc;
std::stop_token st = ssrc.get_token();
std::thread t(worker_with_callback, st);
std::this_thread::sleep_for(std::chrono::seconds(3));
ssrc.request_stop();
t.join();
return 0;
}
这里需要注意,stop_callback的生命周期至少要覆盖到停止请求可能被发起的时间段,否则回调可能无法正常执行。
与std::jthread的配合
C++20还新增了std::jthread(joining thread),它内部自动集成了stop_token的支持,并且会在析构时自动调用join(),进一步简化线程管理:
#include <iostream>
#include <thread>
#include <chrono>
void jthread_worker(std::stop_token st) {
int count = 0;
while (!st.stop_requested()) {
std::cout << "jthread运行中,计数: " << count++ << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "jthread收到停止请求,退出" << std::endl;
}
int main() {
// 创建jthread,自动传入stop_token
std::jthread t(jthread_worker);
// 主线程等待3秒
std::this_thread::sleep_for(std::chrono::seconds(3));
// 调用jthread的request_stop方法发起停止请求
t.request_stop();
// jthread析构时会自动join,不需要手动调用
return 0;
}
std::jthread的构造函数会自动创建stop_source,并将对应的stop_token传入线程函数,同时提供了request_stop()方法直接发起停止请求,大幅减少了模板代码。
使用注意事项
- std::stop_token的停止检查是协作式的,线程必须主动调用
stop_requested()方法查询状态,不会强制终止线程,避免了强制终止带来的资源泄漏问题。 - stop_source和stop_token的关联是单向的,stop_token只能查询状态,不能发起停止请求,停止请求只能由stop_source发起。
- 如果stop_source在关联的stop_token被销毁后才发起停止请求,不会影响已经销毁的token,也不会产生未定义行为。
- 不要在stop_callback的回调函数中执行耗时过长的操作,否则会阻塞request_stop()方法的执行。
与传统停止方式对比
下面通过表格对比std::stop_token和传统停止方式的差异:
| 对比项 | std::stop_token方式 | 传统原子变量方式 |
|---|---|---|
| 标准化程度 | C++20标准内置,跨平台行为一致 | 手动实现,不同实现可能有差异 |
| 线程安全性 | 标准库保证内部状态线程安全 | 需要手动保证原子变量的正确操作 |
| 协作性 | 原生支持协作停止,可注册回调 | 需要手动实现回调逻辑 |
| 代码复杂度 | 代码简洁,逻辑清晰 | 需要额外定义共享变量,代码繁琐 |
可以看出,std::stop_token在易用性、安全性和标准化程度上都优于传统的线程停止方式,是C++20之后多线程停止场景的首选方案。
C++20std::stop_token线程停止协作模式修改时间:2026-07-05 04:18:28