C++原子操作中线程无法读取已更新指针值的原因咨询
问题分析:为什么线程A会覆盖线程B的ptr值
首先看问题中的代码实现:
#include <memory> #include <iostream> #include <atomic> class A { public: A * get() { if(nullptr == ptr.load(std::memory_order_acquire)) { ptr.store(new A(),std::memory_order_release); } return ptr.load(std::memory_order_acquire); } inline static std::atomic<A*> ptr = nullptr; }; int main() { return 0; }
核心问题:执行流程不可回退,缺少二次检查
你提到的场景里,线程A并非看不到线程B更新后的ptr值,而是它的执行流程已经跳过判断步骤,不会再去读取更新后的ptr:
- 线程A先执行
ptr.load(std::memory_order_acquire),得到nullptr后进入if代码块; - 此时线程B也执行
ptr.load,同样得到nullptr(即便后续线程B完成了store操作,线程A也已经走完if判断,不会重新检查); - 线程B先完成
ptr.store(new A(), std::memory_order_release),通过release-acquire内存序的保证,这个写入结果对线程A是可见的; - 但线程A已经处于if块内部,不会再次读取ptr的值,会继续执行自己的
store操作,直接覆盖线程B写入的ptr值。
内存序的作用局限
std::memory_order_acquire和std::memory_order_release仅能保证:
- 线程B的store操作(release)之前的所有写入,对后续执行load(acquire)的线程可见;
- 但它们无法改变线程A进入if块后的执行逻辑——线程A不会因为ptr已被其他线程修改,就回溯重新判断条件。
修复方向
要避免这个问题,需要实现双重检查锁定(Double-Checked Locking):在进入临界区(比如加锁后),再次检查ptr是否仍为nullptr,确认后再执行初始化操作。
内容的提问来源于stack exchange,提问作者getsoubl
相关产品推荐
相关产品推荐

