You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用stop_token等待condition_variable_any时,请求停止是否需持有锁?

关于std::jthread request_stop()与条件变量的同步规范问题

在等待条件变量时,修改谓词状态的线程必须持有锁,避免唤醒期间错过更新——哪怕用原子变量,标准文档也要求这么做。但我不确定request_stop()是否需要遵循这个规则,想知道以下两种调用方式哪种符合标准规范?

另外,~jthread()调用request_stop()时自然不会持有锁,但我搞不懂stop_token和原子共享变量的区别:为什么前者调用request_stop()不需要锁,后者修改时却必须持有?

代码示例

#include <thread>
#include <condition_variable>
#include <iostream>
#include <chrono>

std::mutex m;
std::condition_variable_any cv;

void waitingThread(std::stop_token st){
    std::unique_lock<std::mutex> lk(m);
    std::cout<<"Waiting"<<std::endl;
    cv.wait(lk, st, [](){return false;});
    std::cout<<"Awake"<<std::endl;
}

void withoutLock(){
    std::jthread jt{waitingThread};
    std::this_thread::sleep_for(std::chrono::seconds(1));
    jt.request_stop();
}

void withLock(){
    std::jthread jt{waitingThread};
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lk(m);
        jt.request_stop();
    }
}

int main(){
    withoutLock();
    withLock();
}

相关标准文档说明

std::condition_variable的文档指出:即使共享变量是原子的,也必须在持有互斥锁的情况下修改它,才能将修改正确发布给等待线程。

而std::condition_variable_any::wait、std::stop_token和std::stop_source的文档未明确说明等待中断是否能保证记录停止状态的变更。


解答

哪种方式符合标准规范?

两种方式都符合标准规范,核心原因是condition_variable_any::wait与stop_token的集成实现,已经内部处理了同步问题,不需要额外手动加锁保护request_stop()的调用。

为什么stop_token不需要锁,而原子变量需要?

  1. stop_token的内部同步机制:stop_token和stop_source是C++20专为协作式停止设计的组件,它们的内部已经保证了停止状态的原子性修改与跨线程可见性。调用request_stop()时,不仅会原子性设置停止标记,还会自动触发所有关联等待操作(比如cv.wait(lk, st, ...))的唤醒——这个过程和条件变量的等待逻辑深度绑定,无需外部锁介入同步。

  2. 原子变量的竞态风险:当自定义原子变量作为谓词一部分时,持锁修改是为了避免丢失唤醒的竞态:比如等待线程刚检查完谓词为false、释放锁准备休眠的间隙,修改线程修改了原子变量但还没调用notify_one(),此时等待线程会错过唤醒陷入永久休眠。而stop_token与condition_variable_any::wait的组合已经消除了这个风险:等待逻辑在检查停止状态和进入休眠的过程中,内部保证不会错过request_stop()的通知。

  3. jthread析构的合理性:~jthread()调用request_stop()无需锁,正是因为stop_token的内部同步机制已经足够安全,不需要依赖外部互斥锁来保证状态发布的正确性。


内容的提问来源于stack exchange,提问作者CGlas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 03:45:33