了解发布顺序并在C11中与之同步

时间:2019-04-12 07:56:23

标签: c multithreading concurrency c11 memory-model

我试图了解内存模型并读取5.1.2.4 Multi-threaded executions and data races,并且对5.1.2.4(p10)定义的发布顺序概念感到困惑,如下所示:

  

以原子对象上的释放操作A为首的释放序列   M是副作用中最大的连续子序列   M的修改顺序,其中第一个操作是A,每个   后续操作由同一线程执行   执行了发布操作,或者是原子的读-修改-写操作。

随后用于定义与5.1.2.4(p11)的同步,如下所示:

  

某些库调用与执行的其他库调用同步   通过另一个线程。特别是,原子操作A   对对象M执行释放操作,该对象与   对B执行获取操作的原子操作M和   读取释放序列中任何副作用写入的值   以A为首。

我可以想象以下示例:

#include <stdatomic.h>
Atomic_ int a; // <<--- M

int main(void){
    atomic_store_explicit(&a, 42, memory_order_release); // <<--- A
    atomic_store_explicit(&a, 442, memory_order_release); 
    atomic_store_explicit(&a, 242, memory_order_release); 
    int a_value = atomic_load_explicit(&a, memory_order_acquire);
    atomic_store_explicit(&a, 242, memory_order_release);
}

我目前将其理解为Aatomic_store_explicit(&a, 42, memory_order_release);,其发布顺序是

atomic_store_explicit(&a, 442, memory_order_release); 
atomic_store_explicit(&a, 242, memory_order_release); 

但是不包括atomic_store_explicit(&a, 242, memory_order_release);,因为它后面是int a_value = atomic_load_explicit(&a, memory_order_acquire);,这是一个获取操作。

现在进入synchronize with 对对象M执行释放操作的原子操作A与对M执行获取操作并读取任何副作用写入的值的原子操作B同步表示A的释放顺序中的所有释放操作都可以通过atomic_load_explicit(&a, memory_order_acquire);

的获取操作看到

是正确的还是我错过了什么?

1 个答案:

答案 0 :(得分:3)

否,该序列包括所有四个存储操作,因为中间加载操作是由同一线程完成的。基本上,对于您的示例,您不必引用同步。由于游戏中只有一个线程,因此“先于先后”已经为您提供了所需的所有信息。一个优化器甚至可以省略除了简化示例中的最后一个存储之外的所有存储,即使是原子操作也是如此。 (嗯,volatile的规范中有atomic_store,但是暂时让我们忘记这一点。)

我认为,释放序列概念的思想是识别不同线程的读取可能会拦截存储值的点,并使这些点在序列中的第一次存储操作之后依存于读取顺序。为此,可以忽略线程读取已写入的值的事实。