gpt4 book ai didi

c++ - 为什么 'acquire/release'在c++11中不能保证顺序一致性?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:42:28 31 4
gpt4 key购买 nike

-Thread 1-                
y.store (20, memory_order_release);
x.store (10, memory_order_release);

-Thread 2-
if (x.load(memory_order_acquire) == 10) {
assert (y.load(memory_order_acquire) == 20);
y.store (10, memory_order_release)
}

-Thread 3-
if (y.load(memory_order_acquire) == 10) {
assert (x.load(memory_order_acquire) == 10);
}

GCC Atomic Wiki “Overall Summary”段落说,上面的代码assert(x.load(memory_order_acquire))可以失败。但我不明白为什么?

我的理解是:

  1. 由于 acquire 屏障,Thread3 无法LoadLoad 重新排序。
  2. 由于释放 障碍,Thread1 无法StoreStore 重新排序。
  3. 当 Thread2 read(x)->10 时,x 必须从 storebuffer 刷新到 Thread1 的缓存中,这样每个线程都知道 x 的值发生了变化,例如使缓存行无效。
  4. Thread3 使用Acquire 屏障,因此它可以看到 x(10)。

最佳答案

这是一个糟糕的例子,但我想它确实说明了松散的原子是多么令人费解。

[介绍.执行]p9:

Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.

[atomics.order]p2:

An atomic operation A that performs a release operation on an atomic object M synchronizes with an atomic operation B that performs an acquire operation on M and takes its value from any side effect in the release sequence headed by A.

因此,显示的评估通过 sequenced-before 和 synchronized-with 关系链接在一起:

Thread 1                   Thread 2              Thread 3

y.store(20)
|
| s.b.
V s.w.
x.store(10) --------> x.load() == 10
|
| s.b.
V s.w.
y.store(10) --------> y.load() == 10
|
| s.b.
V
x.load() == ?

因此链中的每个评估发生在下一个之前(参见 [intro.races]p9-10)。

[intro.races]p15,

If a value computation A of an atomic object M happens before a value computation B of M, and A takes its value from a side effect X on M, then the value computed by B shall either be the value stored by X or the value stored by a side effect Y on M, where Y follows X in the modification order of M.

这里,A 是线程 2 中取值为 10 的负载,B 是线程 3 中的负载(在断言中)。由于 A 发生在 B 之前,并且 x 没有其他副作用,因此 B 也必须读取 10。


Herb Sutter 有一个更简单的例子 on his blog :

T1: x = 1;
T2: y = 1;
T3: if( x == 1 && y == 0 ) puts("x first");
T4: if( y == 1 && x == 0 ) puts("y first");

您绝对需要顺序一致性来保证最多打印一行。

关于c++ - 为什么 'acquire/release'在c++11中不能保证顺序一致性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50441014/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com