协作取消
内容介绍
C++ 没有安全的“强杀线程”标准 API。线程退出应由任务自己检查停止信号,然后主动结束。
C++20 提供 std::jthread 和 std::stop_token,可以表达协作式取消。取消能力的性能意义是:任务停止时不拖住线程池,不让无用任务继续占用工作线程。
jthread + stop_token
#include <chrono>
#include <iostream>
#include <thread>
using namespace std::chrono_literals;
int main() {
std::jthread worker([](std::stop_token st) {
while (!st.stop_requested()) {
std::cout << "working\n";
std::this_thread::sleep_for(100ms);
}
std::cout << "stopped\n";
});
std::this_thread::sleep_for(350ms);
worker.request_stop();
}std::jthread 析构时也会请求停止并等待线程结束。
C++11/17 停止标志
std::atomic<bool> stop = false;
std::thread worker([&] {
while (!stop.load()) {
// do work
}
});
stop.store(true);
worker.join();最佳代码实践
- 长循环任务必须设计停止条件。
- 阻塞等待任务要能被唤醒退出,例如关闭 Channel 或
notify_all。 - C++20 优先用
std::jthread和stop_token。 - C++17 及以前使用
atomic<bool>或关闭队列表达停止。
常见错误用法
while (true) {
do_work();
}问题:线程没有退出路径,程序关闭时只能泄漏、卡住或强制终止。
worker.detach();
// 希望进程退出时后台线程自己安全结束问题:detach 后生命周期不可控,通常不是工程级退出方案。
注意事项
- 取消是协作式的:请求停止不等于立即停止。
- 如果线程卡在不可中断 IO,
stop_token本身无法把它唤醒。 - 关闭队列、条件变量通知、超时等待经常要和取消信号配合使用。
学习路径
- 上一节:cpp线程池
- 当前阶段:cpp多线程
- 暂时终点