可以使用C11围栏来推断其他线程的写入吗?

图4b中的Adve和Gharachorloo的报告提供了以下在没有顺序一致性的情况下表现出意外行为的程序示例:

在此处输入图像描述

我的问题是,是否有可能只使用C11栅栏和memory_order_relaxed加载和存储来确保register1(如果写入)将被写入值1.抽象中可能难以保证的原因是P1,P2并且P3可以在病理性NUMA网络中的不同点处具有P2在P3之前看到P1的写入的属性,但是不知何故P3看到P2的写入非常快。 特别是对C11规范难以保证的原因是P1写入A和P2的A读取不会相互同步,因此规范的5.1.2.4.26段将导致未定义的行为。 可能我可以通过放松的primefaces提取/存储来回避未定义的行为,但我仍然不知道如何对P3所看到的顺序进行过渡性推理。

下面是一个试图用栅栏解决问题的MWE,但我不确定它是否正确。 我特别担心释放栅栏不够好,因为它不会刷新p1的存储缓冲区,只是p2的。 但是,它会回答我的问题,如果你可以认为断言永远不会失败只是基于C11标准(而不是一些关于特定编译器和架构的其他信息)。

 #include  #include  #include  #include  atomic_int a = ATOMIC_VAR_INIT(0); atomic_int b = ATOMIC_VAR_INIT(0); void p1(void *_ignored) { atomic_store_explicit(&a, 1, memory_order_relaxed); } void p2(void *_ignored) { if (atomic_load_explicit(&a, memory_order_relaxed)) { atomic_thread_fence(memory_order_release); // not good enough? atomic_store_explicit(&b, 1, memory_order_relaxed); } } void p3(void *_ignored) { int register1 = 1; if (atomic_load_explicit(&b, memory_order_relaxed)) { atomic_thread_fence(memory_order_acquire); register1 = atomic_load_explicit(&a, memory_order_relaxed); } assert(register1 != 0); } int main() { thrd_t t1, t2, t2; thrd_create(&t1, p1, NULL); thrd_create(&t2, p2, NULL); thrd_create(&t3, p3, NULL); thrd_join(&t1, NULL); thrd_join(&t2, NULL); thrd_join(&t3, NULL); } 

你在p3忘记了memory_order_acquire fence:

 void p3(void *_ignored) { int register1 = 1; if (atomic_load_explicit(&b, memory_order_relaxed)) { atomic_thread_fence(memory_order_acquire); // <-- Here register1 = atomic_load_explicit(&a, memory_order_relaxed); } assert(register1 != 0); } 

使用这个围栏,在p2加载a发生与之前的关系。

C11标准保证了读 - 读相干性,这意味着p3中的加载应该观察到相同或后续的修改 ,这可以通过p2 发生的加载观察到。 因为p2的加载会在p1观察存储,并且在您的方案中不能对a 进行后续修改, ap3加载也应该观察到存储在p1

所以你的断言永远不会触发。


参考标准中的相应陈述

5.1.2.4 p.25:程序的执行包含数据竞争,如果它在不同的线程中包含两个冲突的动作,其中至少有一个不是primefaces的 ,并且都不会在另一个之前发生。 任何此类数据争用都会导致未定义的行为。

因此,根据定义, primefaces访问不能包含数据竞争。

5.1.2.4 p.22:......如果primefaces对象M的值计算A发生在M的值计算B之前,并且由A计算的值对应于由副作用X存储的值,则计算的值由B应该等于A计算的值,或者是副作用Y存储的值,其中Y在M的修改顺序中跟随X.

下一段说,这是缓存一致性保证 。 C ++ 11标准更具体,并说明了类似措辞中的读 - 读缓存一致性