首页 > 解决方案 > 了解发布顺序并与 C11 同步

问题描述

我试图理解内存模型和读取,并且对定义如下5.1.2.4 Multi-threaded executions and data races的释放序列概念感到困惑:5.1.2.4(p10)

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

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

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

我可以想象下面的例子:

#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);
}

我目前将其理解为A存在atomic_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 执行获取操作并读取由 A 为首的释放序列中的任何副作用写入的值的原子操作 B 同步。意味着A 的释放序列中的所有释放操作都可以通过获取操作可见,该操作是atomic_load_explicit(&a, memory_order_acquire);

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

标签: cmultithreadingconcurrencyc11memory-model

解决方案


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

我认为,释放序列概念的想法是识别不同线程的读取可能截取存储值的点,并在序列中的第一个存储操作之后使读取依赖排序。为此,可以忽略线程读取它已写入的值的事实。


推荐阅读