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

基于原子变量的线程间同步中全局变量读取的正确性疑问

基于原子变量的线程间同步中全局变量读取的正确性疑问

嘿,这个问题问得很接地气,咱们先把你的代码完整整理出来,再一步步拆解分析:

#include <atomic>
#include <thread>

std::atomic<int> counter = 0; // 默认memory_order_seq_cst
int globalInt1;
int globalInt2;
int globalInt3;

void Wait() { /* 假设这里是不影响同步逻辑的等待操作 */ }

void thread1() {
    globalInt1 = 1;
    --counter;
    Wait();
}

void thread2() {
    globalInt2 = 2;
    --counter;
    Wait();
}

void thread3() {
    globalInt3 = 3;
    --counter;
    Wait();
}

int main() {
    ++counter;
    ++counter;
    ++counter;
    std::thread{ thread1 }.detach();
    std::thread{ thread2 }.detach();
    std::thread{ thread3 }.detach();
    while (counter != 0); // 循环退出后读取globalInt1~3是否正确?
}

你的核心疑问是:main线程等到counter变为0后,能不能确保正确读到globalInt1、globalInt2、globalInt3的赋值结果,还是说只能和最后修改counter的那个线程同步?

答案是:你完全可以在main线程里正确读取到三个全局变量的赋值结果,不会出现只能和最后一个修改counter的线程同步的情况,具体原因如下:

  • 首先,std::atomic<int>默认的内存序是memory_order_seq_cst,这种内存序会给所有原子操作强制一个全局总顺序——也就是说,所有线程看到的counter的增减操作顺序是完全一致的,不存在各线程看到不同操作顺序的情况。
  • 其次,在每个工作线程内部,globalIntX = X的赋值操作,和对应的--counter原子操作之间存在**happens-before(先行发生)**关系:同一个线程里,按代码顺序执行的操作,前面的操作必然先行发生于后面的操作,再加上memory_order_seq_cst的约束,编译器和CPU都不会对这些操作进行重排序。
  • 然后,main线程里的三次++counter操作,先行发生于三个工作线程的启动(因为main线程先执行完所有递增,才创建并启动工作线程);而只有当三个工作线程的--counter操作全部执行完毕后,counter才会回到0,main线程的循环才会退出。

根据C++内存模型的传递性规则:如果操作A先行发生于B,B先行发生于C,那么A先行发生于C。这里每个globalIntX = X先行发生于对应的--counter,所有--counter又先行发生于main线程看到counter == 0的读取操作,因此每个全局变量的赋值操作,都先行发生于main线程后续对它们的读取操作。这就保证了main线程读取到的一定是三个工作线程赋值后的正确值,不会是未初始化的垃圾值或者旧值。

你担心的“只能和最后修改counter的线程同步”的情况,不会在memory_order_seq_cst的场景下出现——全局总序确保了所有原子操作的顺序都被全局可见,先行发生关系的传递性也覆盖了所有工作线程的赋值操作到main读取的完整路径。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 07:09:29