我在学习记忆障碍。我有一些关于代码的问题。
//version 1
Thread A:
*val = 1;
atomic_thread_fence(memory_order_release);
atomic_store_explicit(published, 1, memory_order_relaxed);
Thread B:
if (atomic_load_explicit(published, memory_order_relaxed) == 1) {
atomic_thread_fence(memory_order_acquire);
assert(*val == 1); // will never fail
}
//version 2
/* Thread A */
*val = 1;
atomic_thread_fence(memory_order_release);
*published = 1;
/* Thread B */
if (*published == 1) {
atomic_thread_fence(memory_order_acquire);
assert(*val == 1); /* may fail */
}
- atomic_thread_fence是否只影响原子加载/存储,它对编译器有任何影响还是只对cpu有影响?
1.在版本2中,要发布的存储是非原子的,它怎么会由于使用atomic_thread_fence而导致Assert失败,atomic_thread_fence仅用于原子加载/存储?
1.为什么 * 瓦尔= 1不写成atomic_store_explicit(val,1,memory_order_relaxed)?
1条答案
按热度按时间bsxbgnwa1#
1.栅栏确实影响非原子的加载和存储。例如,无论是否是原子的加载或存储,都不能在获取栅栏之前重新排序。否则栅栏将无法建立必要的同步。“重新排序”包括内存中指令的编译时重新排序,以及运行时乱序执行;栅栏必须同时阻止它们。
1.这并不是说围栏“只适用于原子”操作,只是假设
published
在版本2中是非原子的,那么published
上就会有数据竞争:你在不同的线程中有两个非原子访问,至少其中一个是写,并且没有同步来使其中一个在另一个之前发生。在这里,栅栏不是一个问题,只是它们没有做任何事情来帮助避免数据竞争。释放/获取栅栏只有在与观察原子存储值的原子加载一起使用时才有效。在其他上下文中,它们是无害的,但也是无用的。
1.在版本1中,
*val
可以安全地进行非原子访问。(到published
,值为1),以及如果它观察到存储,则跟随有获取围栏的加载。这正是C17标准中7.17.4p2的设置,因此释放围栏与获取围栏同步因此,*val
的存储发生在*val
的加载之前(如果加载发生的话),所以在*val
上没有数据竞争,并且加载保证观察存储的值(5.1.2.4p20)。在published
上也没有数据竞争,因为它是原子的。