C++中release-acquire内存序的真实语义是什么?
深入理解C++原子操作的release-acquire内存序
本文旨在拆解C++原子操作中release-acquire内存序的细节,先明确对该语义的理解,再针对某书籍示例提出疑问,最后给出更贴合语义的阐释示例。
1. 对release-acquire语义的理解(参考C++官方文档cppreference)
memory_order_release(释放语义):
- 当前线程内所有读、写操作不能重排至该存储操作之后
- 本质是保证线程内部的
load->store(读转写)和store->store(写转写)操作顺序不被打乱。
- 本质是保证线程内部的
- 当前线程的所有写操作对获取同一原子变量的其他线程可见
- 一旦该释放操作进入全局一致性顺序,当前线程对原子变量的写操作会对所有执行该原子变量获取操作的线程同时可见,而非仅针对个别线程。
memory_order_acquire(获取语义):
- 当前线程内所有读、写操作不能重排至该加载操作之前
- 本质是保证线程内部的
load->load(读转读)和load->store(读转写)操作顺序不被打乱。
- 本质是保证线程内部的
- 其他线程释放同一原子变量的所有写操作对当前线程可见
- 其他线程对该原子变量的任何释放操作,都会被当前线程的获取操作观测到,不存在仅对部分获取线程可见的情况。
2. 对某书籍中release-acquire示例的疑问(该案例改编自cppreference的顺序一致性示例)

该书籍称示例中的assert最终会触发,但我在x86和ARM平台测试后从未复现这一结果,结合release-acquire语义的理解,疑问如下:
- 释放操作的存储结果对所有执行获取操作的线程全局可见,原子变量X和Y的写操作必然存在全局顺序,线程c和d应当看到完全一致的结果:要么先X后Y,要么先Y后X,绝不可能出现c看到X->Y而d看到Y->X的情况。
- release-acquire仅保证以下操作顺序不被重排:
Store->Store(写转写)Load->Store(读转写)Load->Load(读转读)
但不保证Store->Load(写转读)的顺序。而该示例的代码逻辑未涉及Store->Load模式,理论上应能保证内存操作的全局一致性,不会出现触发assert的情况。
3. 更贴合release-acquire语义的阐释示例

该示例通过release-acquire模型操作原子变量,并在每个线程内构造Store->Load语义。由于release-acquire不保证Store->Load的操作顺序,两个线程极有可能均无法完成预期逻辑,最终导致assert失败,能更准确地体现release-acquire内存序的边界特性。
内容的提问来源于stack exchange,提问作者nazavoya
相关产品推荐
相关产品推荐

