简体   繁体   English

为什么“获取/释放”不能保证 c++11 中的顺序一致性?

[英]Why 'acquire/release' can not guarantee sequential consistency in c++11?

-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 paragraph “Overall Summary” says, the above code assert(x.load(memory_order_acquire)) can fail . GCC Atomic Wiki段落“Overall Summary”说,上面的代码assert(x.load(memory_order_acquire))可能会失败 But I don't understand why ?但我不明白为什么?

My understanding is:我的理解是:

  1. Thread3 can not LoadLoad reorder due to acquire barrier.由于获取障碍,线程 3 无法LoadLoad重新排序。
  2. Thread1 can not StoreStore reorder due to release barrier.由于释放障碍,线程 1 无法对StoreStore重新排序。
  3. When Thread2 read(x)->10, x must be flushed from storebuffer to cache in Thread1, so every thread know the value x has changed, such as invalidate cache line.当 Thread2 read(x)->10 时,x 必须从 storebuffer 刷新到 Thread1 中的缓存,所以每个线程都知道 x 的值发生了变化,例如使缓存行无效。
  4. Thread3 uses Acquire barrier, so it can see x(10). Thread3 使用Acquire屏障,所以它可以看到 x(10)。

This is a bad example, though it does illustrate how mind-warping relaxed atomics can be, I suppose.这是一个糟糕的例子,尽管我想它确实说明了放松的原子是多么令人费解。

[intro.execution]p9: [介绍.执行]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: [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 .对原子对象M执行释放操作的原子操作A与对M执行获取操作的原子操作B同步,并从以A为首的释放序列中的任何副作用中获取其值。

As a result, the evaluations shown are chained together by sequenced-before and synchronized-with relationships:因此,显示的评估通过先序和同步关系链接在一起:

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() == ?

And so each evaluation in the chain happens before the next (see [intro.races]p9-10).因此,链中的每个评估都发生在下一个之前(参见 [intro.races]p9-10)。

[intro.races]p15, [介绍.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 .如果一个原子对象M的值计算A M的值计算B之前发生,并且AM上的副作用X取它的值,然后用B中计算出的值应要么是或者存储在由X所存储的值的值由M上,副作用ÿ其中Y如下XM的修改次序。

Here, A is the load in Thread 2 that took the value 10, B is the load in Thread 3 (in the assert).这里, A是线程 2 中取值为 10 的负载, B是线程 3 中的负载(在断言中)。 Since A happens before B , and there are no other side effects on x , B must also read 10.由于A发生在B之前,并且对x没有其他副作用,因此B也必须读取 10。


Herb Sutter has a much simpler example on his blog : Herb Sutter 在他的博客上有一个更简单的例子:

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

You absolutely need sequential consistency to guarantee that at most one line is printed.您绝对需要顺序一致性来保证最多打印一行。

Your example is special case of multithread program that only use atomic objects for synchronization, not for communicating information with significant entropy: the only values written act as milestones .您的示例是多线程程序的特例,它仅使用原子对象进行同步,而不是用于传递具有显着熵的信息:写入的唯一值充当里程碑

It means that any store:这意味着任何商店:

  • is a release operation是一个释放操作
  • communicates a value that indicate a precise point in the progress of one thread传达一个值,该值指示一个线程的进度中的精确点

The form must be exactly A.store (C, memory_order_release);表单必须正好是A.store (C, memory_order_release); where:在哪里:

  • A is an atomic object A是原子对象
  • C is a constant C是常数

and the pair (A,C) characterizes uniquely the program line.和对(A,C)唯一地表征程序行。

And conversely each load:相反,每个负载:

  • is an acquire是一个获得
  • only checks for a particular value只检查特定值

The form must be exactly表格必须完全正确

if (A.load(memory_order_acquire) == C) { ... }

where there is no else clause.没有 else 子句的地方。

Reading a particular value indicates progress and establish that all previous side effect (before a particular program point) have happened.读取特定值指示进度并确定所有先前的副作用(在特定程序点之前)已经发生。 That small class of programs never has funny multithread behavior because everything is a function of progress: milestones are passed, and the behavior must be purely sequential.这一小类程序从来没有有趣的多线程行为,因为一切都是进程的函数:里程碑被传递,行为必须是纯顺序的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C++11中获取/释放VS顺序一致性? - Acquire/Release VS Sequential Consistency in C++11? C ++ 11 std :: atomic是否保证互斥以及顺序一致性? - Does C++11 std::atomic guarantee mutual exclusion as well as sequential consistency? 获取c ++ 11(原子)的发布操作 - Acquire release operation of c++11(atomic) C ++ 11比较和交换获取/发布语义 - C++11 compare and swap acquire/release semantics 可以使用C ++ 11中的后续顺序一致的加载对商店发布进行重新排序吗? - Can a store-release be reordered with a subsequent sequential-consistent load in C++11? C++11 顺序一致性 memory 命令是否禁止存储缓冲区石蕊测试? - Does C++11 sequential consistency memory order forbid store buffer litmus test? C++11 memory_order_acquire 和 memory_order_release 语义? - C++11 memory_order_acquire and memory_order_release semantics? 理解 C++11 中的 `memory_order_acquire` 和 `memory_order_release` - Understanding `memory_order_acquire` and `memory_order_release` in C++11 C ++ 11标准是否正式定义了获取,发布和使用操作? - Does the C++11 standard formally define acquire, release, and consume operations? C ++ 11是否允许(不要求)发布/获取volatile关键字的语义 - Does C++11 allow (not require) release/acquire semantics for volatile keyword
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM