C/C++不同CPU核心线程是否可能永远看不到共享变量的写入更新?
问题结论
无法保证线程一定能感知到其他线程对共享普通变量的写入,你给出的示例代码中,thread_B完全有可能永远无法停止。
你给出的原始代码如下:
bool stop = false; // 线程A和B共享的全局变量 // 线程A void thread_A(){ sleep(10); stop = true; } // 线程B void thread_B(){ while(!stop) { // .. 执行业务逻辑 } }
具体原因
- 编译器优化导致可见性失效
C/C默认按单线程语义做编译优化,编译器不知道stop是跨线程共享的变量,所以在编译thread_B的循环逻辑时,完全可以将!stop的判断优化为:第一次循环时读取内存里的stop值存入寄存器,后续循环直接读寄存器判断,不再重读内存。这种优化完全符合C/C的标准要求,哪怕后续内存里的stop被修改为true,thread_B也永远感知不到。 - 内存模型层面的未定义行为
就算手动关闭编译器优化,C++标准也明确规定:没有同步措施的普通跨线程读写属于数据竞争,是未定义行为,哪怕底层CPU实现了缓存一致性协议,也不能保证执行结果符合预期。你提到的写回缓存永远不写回的情况虽然在主流硬件上不会出现,但标准层面根本不保障普通变量的跨线程可见性,出现任何结果都符合标准要求。
修复方案
只需要把共享变量声明为原子变量,即可保证写入的跨线程可见性:
#include <atomic> std::atomic<bool> stop = false; // 全局共享原子变量 // 线程A void thread_A(){ sleep(10); // 释放语义写入 stop.store(true, std::memory_order_release); } // 线程B void thread_B(){ // 获取语义读取 while(!stop.load(std::memory_order_acquire)) { // .. 执行业务逻辑 } }
也可以用互斥锁等同步原语保护所有对stop的读写操作,同样能满足可见性要求。
内容的提问来源于stack exchange,提问作者konchy
相关产品推荐
相关产品推荐

