c++怎么使用std::stop_token停止线程_c++ 20线程安全请求中断【方法】

不能。std::stop_token 仅提供协作式中断机制,线程需主动轮询或等待该 token 并自行退出;C++20 不支持强制终止线程,必须配合 std::jthread、std::stop_token 和 stop_callback 或轮询 stop_requested() 实现安全中断。

std::stop_token 能否直接终止正在运行的线程?

不能。std::stop_token 本身不终止线程,它只提供一种协作式中断机制:线程需主动轮询或等待该 token,并在收到停止请求后自行退出。C++20 没有提供强制杀线程的接口(如 pthread_cancel 或旧式 std::thread::kill),这是刻意设计的安全约束。

如何用 std::stop_token 实现安全的线程中断?

核心是三件套配合:std::jthread(自动注册 stop_source)、std::stop_token(传入线程函数)、std::stop_callback 或轮询 stop_token.stop_requested()。推荐优先使用 std::jthread,它比 std::thread 更安全、更简洁。

  • std::jthread 构造时自动关联一个 std::stop_source,析构时自动调用 request_stop()(可禁用)
  • 线程函数参数中接收 std::stop_token,用于检查中断状态
  • 避免在循环中无休止忙等;应在可能阻塞点(如 sleep_forwaitread)插入轮询或使用支持 stop_token 的等待函数(如 std::condition_variable::wait 重载)
#include 
#include 
#include 

void worker(std::stop_token stoken) {
    for (int i = 0; i < 10; ++i) {
        if (stoken.stop_requested()) {
            std::cout << "worker: stopping early at " << i << "\n";
            return;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        std::cout << "worker: step " << i << "\n";
    }
}

int main() {
    std::jthread t{worker};
    std::this_thread::sleep_for(std::chrono::milliseconds(700));
    t.request_stop(); // 主动触发停止
    // t.join(); // jthread 析构会自动 join,除非已 detach
}

std::stop_token 在条件变量等待中怎么用?

直接传入 std::condition_variable::wait 的重载版本,它会在被唤醒或收到 stop 请求时返回,并通过 stop_token.stop_requested() 判断原因。这是比手动轮询更高效、更及时的中断方式。

  • 必须使用支持 stop_tokenwait 重载(签名含 std::stop_token 参数)
  • 该重载内部会注册临时回调,确保即使等待被虚假唤醒也能响应中断
  • 返回后应先检查 stoken.stop_requested(),再处理条件逻辑,避免漏掉中断信号
#include 
#include 
#include 
#include 

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void waiter(std::stop_token stoken) {
    std::unique_lock lk{mtx};
    // 等待 ready 为 true,或 stop 请求到来
    cv.wait(lk, stoken, []{ return ready; });
    if (stoken.stop_requested()) {
        std::cout << "waiter: interrupted before ready\n";
        return;
    }
    std::cout << "waiter: ready is true\n";
}

常见错误:把 stop_token 当成“取消句柄”滥用

有人试图在线程外反复调用 stop_source.request_stop() 多次,或在已停止的 token 上做无效轮询,这不会报错但毫无意义——stop_requested() 一旦为 true 就永远为 true,且多次 request_stop 是幂等的。真正容易出问题的是:

  • 在线程函数中未接收 std::stop_token 参数,导致完全无法响应中断
  • 使用 std::thread 却没手动管理 std::stop_source,造成 token 始终无效
  • 在 long-running 计算循环中不轮询,导致中断延迟数秒甚至更久
  • 误以为 std::jthread::request_stop() 会立即暂停执行——它只是发信号,线程何时响应取决于你代码里哪里检查

协作式中断的关键不在 token 本身,而在于你是否在合理位置埋了检查点。没有检查,token 就是张废纸。