以下示例中的第29.3.9和29.3.10节,第1111-1112节中的当前C++0x draft州:
// Thread 1
r1 = y.load(memory_order_relaxed);
x.store(1, memory_order_relaxed);
// Thread 2
r2 = x.load(memory_order_relaxed);
y.store(1, memory_order_relaxed);
结果r1 = r2 = 1
是可能的,因为每个线程的操作都是放宽的,并且是不相关的地址。现在我的问题是关于以下(类似)示例的可能结果:
// Thread 1
r1 = y.load(memory_order_acquire);
x.store(1, memory_order_release);
// Thread 2
r2 = x.load(memory_order_acquire);
y.store(1, memory_order_release);
我认为在这种情况下,结果r1 = r2 = 1
是不可能的。如果可能的话,y的负载将与商店同步(因此发生在之前)。与x类似,x的加载将在商店到x之前发生。但是y的负载在存储到x之前(因此也发生在 - 之前)被排序。这创造了一个循环发生在之前的关系,我认为是不允许的。
答案 0 :(得分:4)
如果我们花时间(或指令序列,如果你喜欢)向下流动,就像阅读代码一样,那么我的理解是
换句话说,如果你有像
这样的代码acquire
// other stuff
release
然后内存访问可能会从获取/释放对之外移动到内部,但不是相反(并且它们也可能不会完全跳过获取/释放对)。
使用问题中第一个示例中的宽松一致性语义,硬件可以重新排序内存访问,以便存储在加载之前进入内存系统,从而允许r1 = r2 = 1。使用第二个示例中的获取/释放语义,可以防止重新排序,因此r1 = r2 = 1是不可能的。