memory_order:acquire/release反向同步模式的技术咨询
关于std::atomic反向同步模式的实现
问题背景
已知std::atomic的标准同步模式(写入后同步)可保证读取线程看到同步标记后,能获取到已写入的数据。现在希望实现写入前同步的反向模式:当读取线程检测到同步标记未被设置时,确保读取到的非原子数据data为初始值(0)。
正确的代码实现及内存序说明
写入线程
sync_before_write.store(1, std::memory_order_release); // 阻止后续data写入被重排到此操作之前 data = 42;
- 使用
std::memory_order_release的原因:该内存序禁止当前线程中所有在该store之后的内存操作被重排到该store之前。这确保了只有当sync_before_write被成功设为1后,写入线程才会开始修改data,不会出现data先被修改、同步标记后设置的情况。
读取线程
data_copy = data; if (sync_before_write.load(std::memory_order_seq_cst) == 0) { // 阻止data读取被重排到此操作之后 assert(data_copy == 0); // 断言必然成立 }
- 使用
std::memory_order_seq_cst的原因:该内存序强制线程内的操作顺序与全局总顺序一致,确保data_copy = data的读取操作不会被编译器或CPU重排到sync_before_write.load()之后。当load返回0时,说明写入线程尚未执行sync_before_write.store(1),结合写入线程的内存序保证,写入线程也尚未修改data,因此data_copy必然是初始值0。
轻量内存序替代方案
如果想追求更优性能,可通过原子栅栏(fence)替代memory_order_seq_cst:
// 读取线程 data_copy = data; std::atomic_thread_fence(std::memory_order_acquire); // 阻止data读取被重排到栅栏之后 if (sync_before_write.load(std::memory_order_relaxed) == 0) { assert(data_copy == 0); }
栅栏的memory_order_acquire同样能阻止之前的内存操作(data读取)被重排到栅栏之后,达到和memory_order_seq_cst相同的效果,但开销更低。
内容的提问来源于stack exchange,提问作者TruLa
相关产品推荐
相关产品推荐

