使用memory_order_seq_cst与memory_order_release时one和two是否可能均为0?
结论
上述代码运行时,one 和 two 完全有可能同时为 0。
对应代码
auto x = std::atomic<std::uint64_t>{0}; auto y = std::atomic<std::uint64_t>{0}; // thread 1 x.store(1, std::memory_order_release); auto one = y.load(std::memory_order_seq_cst); // thread 2 y.fetch_add(1, std::memory_order_seq_cst); auto two = x.load(std::memory_order_seq_cst);
原因解释
- C++ 标准中,
std::memory_order_release仅提供 StoreStore 屏障语义:仅保证当前线程内该操作之前的所有写操作不会被重排到这个 release 操作之后,不会限制后续的读操作被重排到 release 操作之前。 - 线程1中,
y.load(std::memory_order_seq_cst)是读操作,完全可以被重排到前面的x.store(1, std::memory_order_release)之前执行,此时读到的 y 值为 0,即one = 0。 - 线程2中两个操作都是
std::memory_order_seq_cst,同线程内的 seq_cst 操作不允许重排,所以y.fetch_add一定在x.load之前执行。 - 完全可以构造出符合所有内存序规则的执行顺序:
- 线程1重排后先执行
y.load,拿到 y=0,one=0 - 线程2执行
y.fetch_add(1),y 变为 1 - 线程2执行
x.load,此时线程1的x.store还未执行,拿到 x=0,two=0 - 线程1最后执行
x.store(1),运行结束
- 线程1重排后先执行
- 如果把
x.store的内存序换成std::memory_order_seq_cst,所有原子操作都会被纳入全局一致的 seq_cst 总序,就不会出现 one 和 two 同时为 0 的情况。
内容的提问来源于stack exchange,提问作者Curious
相关产品推荐
相关产品推荐

