除了在原子操作中标记 memory ordering 外, 还可以单独使用 fence 指定 memory ordering.Fence 是全局的操作, 它影响所执行线程中其他原子操作的 ordering.
- atomic x,y;
- atomic z;
- void () {
- x.store(true,memory_order_relaxed);
- atomic_thread_fence(memory_order_release);
- y.store(true,memory_order_relaxed);
- }
- void read_y_then_x() {
- while(!y.load(memory_order_relaxed));
- atomic_thread_fence(memory_order_acquire);
- if(x.load(memory_order_relaxed))
- ++z;
- }
上面的代码中, 如果没有显式的 fence,z 的值是不确定的.
关于 fence, 有几个 synchronizes-with 规则:
如果 acquire 操作能读取到位于 release fence 后面 store 的写入的值, 那么这个 fence synchronizes-with acquire 操作.
如果位于 acquire fence 前面的 load 操作能够读取到 release 操作的值, 那么这个 release 操作 synchronizes-with acquire fence.
如果位于 acquire fence 前面的 load 操作能够读取到位于 release fence 后面的 store 写入的值 大专栏 https://www.dazhuanlan.com/ Fence 和非原子操作的 ordering, 那么 release fence synchronizes-with acquire fence.
对于上面的代码, 因为 y 的 load 能够读取到前面写入的值 (由于 fence 存在, 保证了 ordering), 所以 release fence synchronizes-with acquire fence.
- Ordering Nonatomic
- bool x;
- atomic y;
- atomic z;
- void () {
- x = true;
- atomic_thread_fence(memory_order_release);
- y.store(true,memory_order_relaxed);
- }
- void read_y_then_x() {
- while(!y.load(memory_order_relaxed));
- atomic_thread_fence(memory_order_acquire);
- if(x)
- ++z;
- }
现在把前面例子中的 x 换为普通的 x,z 的值仍然是有保证的, y 必须是原子的. fence 保证了 x 的 store 和 y 的 store, 以及 y 的 load 和 x 的 load 之间的 ordering, 而 y 的 store 和 load 之间有 happens-before 关系, 因此 x 的 store 和 load 之间也有 happens-before 关系 (传递).
来源: http://www.bubuko.com/infodetail-3331731.html