C11内存栅栏和原子操作

2lpgd968  于 2023-04-11  发布在  其他
关注(0)|答案(1)|浏览(204)

我在学习记忆障碍。我有一些关于代码的问题。

//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 */
    }
  1. atomic_thread_fence是否只影响原子加载/存储,它对编译器有任何影响还是只对cpu有影响?
    1.在版本2中,要发布的存储是非原子的,它怎么会由于使用atomic_thread_fence而导致Assert失败,atomic_thread_fence仅用于原子加载/存储?
    1.为什么 * 瓦尔= 1不写成atomic_store_explicit(val,1,memory_order_relaxed)?
bsxbgnwa

bsxbgnwa1#

1.栅栏确实影响非原子的加载和存储。例如,无论是否是原子的加载或存储,都不能在获取栅栏之前重新排序。否则栅栏将无法建立必要的同步。“重新排序”包括内存中指令的编译时重新排序,以及运行时乱序执行;栅栏必须同时阻止它们。
1.这并不是说围栏“只适用于原子”操作,只是假设published在版本2中是非原子的,那么published上就会有数据竞争:你在不同的线程中有两个非原子访问,至少其中一个是写,并且没有同步来使其中一个在另一个之前发生。
在这里,栅栏不是一个问题,只是它们没有做任何事情来帮助避免数据竞争。释放/获取栅栏只有在与观察原子存储值的原子加载一起使用时才有效。在其他上下文中,它们是无害的,但也是无用的。
1.在版本1中,*val可以安全地进行非原子访问。(到published,值为1),以及如果它观察到存储,则跟随有获取围栏的加载。这正是C17标准中7.17.4p2的设置,因此释放围栏与获取围栏同步因此,*val的存储发生在*val的加载之前(如果加载发生的话),所以在*val上没有数据竞争,并且加载保证观察存储的值(5.1.2.4p20)。在published上也没有数据竞争,因为它是原子的。

相关问题