C++原子操作acquire/release语义与RMW操作同步问题:单次acquire加载能否与多次release类型RMW操作同步?
C++原子操作acquire/release语义与RMW操作同步问题:单次acquire加载能否与多次release类型RMW操作同步?
嘿,咱们先拆解这个经典的依赖同步场景:线程A、B、C各自独立执行任务,互相不需要同步,但线程D必须等这三个线程全干完,才能合并它们的结果——说白了就是D的执行完全依赖A、B、C的完成状态。
先看给出的基础代码:
int a = 0; int b = 0; int c = 0; std::atomic_int D_dependencies{ 3 };
三个工作线程的代码分别是:
线程A:
a = 1; D_dependencies.fetch_sub(1, std::memory_order_release);
线程B:
b = 1; D_dependencies.fetch_sub(1, std::memory_order_release);
线程C(按场景逻辑补充完整):
c = 1; D_dependencies.fetch_sub(1, std::memory_order_release);
现在核心问题来了:如果线程D用单次acquire语义的load操作来判断D_dependencies是否为0,能不能同时和A、B、C各自的release语义fetch_sub操作建立同步关系?
答案是肯定的,完全没问题。这里得理清几个关键点:
- 首先,
fetch_sub是读-修改-写(RMW)原子操作,当指定std::memory_order_release时,这个操作的释放语义会确保:该线程中所有在fetch_sub之前的写操作(比如A里的a=1),都会被“发布”出去,对后续执行acquire语义操作的线程可见。 - 线程D的
load(std::memory_order_acquire)操作,一旦读取到0,就意味着A、B、C的三次fetch_sub都已经执行完成。这时候,D的acquire加载会和每一次的release语义fetch_sub都建立同步关系——因为原子变量的修改是原子有序的,三次fetch_sub依次把值从3降到0,D读到0的那一刻,必然已经“看到”了所有三次修改的结果。
换句话说,当D成功读到0时,它可以安全地访问a、b、c,因为A、B、C各自在fetch_sub之前的写操作,都已经通过release-acquire的同步关系,确保对D可见了。
举个线程D的示例代码:
// 循环等待所有依赖完成 while (D_dependencies.load(std::memory_order_acquire) != 0) { // 实际场景中可以加std::this_thread::yield()减少空循环占用,但这里重点演示原子同步 } // 此时a、b、c的值都是1,可安全读取合并 int combined_result = a + b + c;
备注:内容来源于stack exchange,提问作者rad
相关产品推荐
相关产品推荐

