std::atomic<T*>用法是否合规?线程断言能否读取预期值?
C++原子指针用法与断言有效性分析
一、std::atomic<T*>的用法是否有效?
代码中std::atomic<Node*>的用法是有效的。无论是全局的ptr变量,还是Node结构体里的next成员,都符合C++标准对原子指针的声明规范;调用store和load进行原子操作的方式也完全合法,没有语法或语义错误。
二、#2和#3处的断言是否一定能读取到#1处写入的值?
#2和#3的断言都无法保证一定会读取到#1处写入的值,核心原因在于内存序的选择:
代码中所有原子操作都使用了std::memory_order::relaxed(松散内存序),这种内存序仅保证操作本身的原子性,不提供任何跨线程的同步或顺序约束:
- 在线程t1内部,
Node对象的成员初始化(#1)确实在ptr.store(r, relaxed)之前执行,但松散内存序允许编译器或CPU对这些操作进行重排序(只要不破坏线程内的依赖逻辑)。 - 线程t2通过
ptr.load(relaxed)拿到非空指针后,由于没有与t1的store操作建立跨线程的synchronizes-with或happens-before关系,无法确保能看到t1中对Node成员的写入——极端情况下,t2可能先读到指针r,但此时r指向的value或next成员还未同步到t2的缓存中,导致断言失败。
如果要让断言必然成立,需要改用释放-获取内存模型:
- 将t1中的
ptr.store(r, std::memory_order::relaxed)改为ptr.store(r, std::memory_order::release) - 将t2中的
ptr.load(std::memory_order::relaxed)改为ptr.load(std::memory_order::acquire)
这样t1的release操作与t2的acquire操作会建立同步关系,t1中store之前的所有写入操作(包括Node成员的初始化)都会对t2可见。
内容的提问来源于stack exchange,提问作者xmh0511
相关产品推荐
相关产品推荐

