在C++20标准中,标准库新增了std::jthread,它是对原有std::thread的封装与增强。两者最核心的区别体现在析构行为和中断机制上,理解这些区别有助于写出更安全、更易维护的并发程序。

一、析构时是否自动合并
std::thread在析构时如果仍处于可连接(joinable)状态,会直接调用std::terminate终止程序。开发者必须手动调用join或detach。而std::jthread在析构时会自动调用join,等待线程执行完毕,降低了资源泄漏和崩溃风险。
#include <iostream>
#include <thread>
#include <chrono>
void old_style() {
std::thread t([] {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "thread donen";
});
// 若忘记 t.join(); 析构时程序终止
}
void new_style() {
std::jthread jt([] {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "jthread donen";
});
// 析构时自动 join,无需手动处理
}
int main() {
old_style();
new_style();
}
二、协作式中断机制
std::thread本身不提供中断能力,通常要自己定义原子布尔变量来通知退出。std::jthread内置了stop_token,线程函数可以接收该令牌,并通过request_stop发起协作中断。
使用stop_token的示例
#include <iostream>
#include <thread>
#include <chrono>
void worker(std::stop_token stoken) {
while (!stoken.stop_requested()) {
std::cout << "working...n";
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
std::cout << "stoppedn";
}
int main() {
std::jthread jt(worker);
std::this_thread::sleep_for(std::chrono::seconds(1));
jt.request_stop(); // 协作中断
}
stop_callback的使用
如果需要在中断时执行清理逻辑,可以使用std::stop_callback注册回调。
#include <iostream>
#include <thread>
void task(std::stop_token stoken) {
std::stop_callback cb(stoken, [] {
std::cout << "cleanup on stopn";
});
while (!stoken.stop_requested()) {}
}
int main() {
std::jthread jt(task);
jt.request_stop();
}
三、两者特性对比
| 特性 | std::thread | std::jthread |
|---|---|---|
| 析构自动join | 否 | 是 |
| 协作中断 | 不支持 | 支持stop_token |
| 构造传参 | 函数与参数 | 支持带stop_token的函数 |
四、如何选择
如果项目使用C++20及以上,并且希望减少手动生命周期管理、需要优雅退出线程,优先使用std::jthread。若必须兼容旧标准或需要detach语义,则继续使用std::thread并自行保证join安全。
jthreadthreadstop_token修改时间:2026-07-26 14:57:14