简体   繁体   English

C++ 原子获取/释放操作的实际含义

[英]C++ atomic acquire / release operations what it actually means

I was going thru this page and trying to understand Memory model synchronization modes.我正在浏览页面并试图了解 Memory model 同步模式。 In below example extracted from there:在下面从那里提取的示例中:

 -Thread 1-       -Thread 2-
 y = 1            if (x.load() == 2)
 x.store (2);        assert (y == 1)

to which states that the store to 'y' happens-before the store to x in thread 1. Is 'y' variable here a normal global variable or is atomic?到哪个声明在线程 1 中存储到“y”之前发生到“x”的存储。这里的“y”变量是普通全局变量还是原子变量?

Further if the load of 'x' in thread 2 gets the results of the store that happened in thread 1, it must all see all operations that happened before the store in thread 1 , even unrelated ones.此外,如果线程 2 中 'x' 的加载获得线程 1 中发生的存储的结果,则它必须全部看到线程 1 中存储之前发生的所有操作,甚至是不相关的操作。

So what it means that x.store() operation would mean that all read / write to memory should have respective memory data values updated?那么 x.store() 操作意味着所有对 memory 的读/写都应该更新相应的 memory 数据值是什么意思?

Then for std::memory_order_relaxed means " no thread can count on a specific ordering from another thread " - what does it means - is it that reordering will be done by compiler that value of y meynot be updated even though y.store() is called?然后对于 std::memory_order_relaxed 意味着“没有线程可以指望来自另一个线程的特定排序”——这是什么意思——重新排序将由编译器完成,即使 y.store() 是,y 的值也不会被更新叫什么?

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

-Thread 2-
if (x.load (memory_order_relaxed) == 10)
  {
    assert (y.load(memory_order_relaxed) == 20) /* assert A */
    y.store (10, memory_order_relaxed)
  }

-Thread 3-
if (y.load (memory_order_relaxed) == 10)
  assert (x.load(memory_order_relaxed) == 10) /* assert B */

For Acquire / release memory model is similar to the sequentially consistent mode, except it only applies a happens-before relationship to dependent variables. For Acquire / release memory model 类似于顺序一致模式,只是它只对因变量应用 happens-before 关系。

Assuming 'x' and 'y' are initially 0:


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

 -Thread 2-
 x.store (10, memory_order_release);

 -Thread 3-
 assert (y.load (memory_order_acquire) == 20 && x.load (memory_order_acquire) == 0)

 -Thread 4-
 assert (y.load (memory_order_acquire) == 0 && x.load (memory_order_acquire) == 10)

What does it means in explicit terms?用明确的术语来说是什么意思?

 -Thread 1-       -Thread 2-
 y = 1            if (x.load() == 2)
 x.store (2);        assert (y == 1)
  1. Naturally, compiler may change order of operations that are not dependent to boost performance.自然地,编译器可能会更改不依赖于提高性能的操作顺序。
    But when std::memory_order_seq_cst is in action, any atomic operator works as memory barrier .但是当std::memory_order_seq_cst 起作用时,任何原子运算符都作为memory barrier工作。
    This does not mean variable y is the atomic, compiler just guarantees that y = 1;这并不意味着变量 y是原子变量,编译器只是保证y = 1; happens before x.store (2);发生在x.store (2); . . If there was another thread 3 that manipulates variable y , assertion may fail due to the other thread.如果有另一个线程 3操作变量 y ,断言可能会由于另一个线程而失败。
    If my explanation is hard to understand(due to my poor English...) please check memory barrier & happened-before .如果我的解释很难理解(由于我的英语不好......)请检查memory barrier & happened-before
    If A happened before B relationship is made, all threads must see the side-effect of A if B 's side-effect has been sighted.如果A发生在B关系建立之前,如果已经看到B的副作用,则所有线程都必须看到A的副作用。
-Thread 1-
y.store (20, memory_order_relaxed)  // 1-1
x.store (10, memory_order_relaxed)  // 1-2

-Thread 2-
if (x.load (memory_order_relaxed) == 10)  // 2-1
  {
    assert (y.load(memory_order_relaxed) == 20) /* assert A */
    y.store (10, memory_order_relaxed)    // 2-2
  }

-Thread 3-
if (y.load (memory_order_relaxed) == 10)  // 3-1
  assert (x.load(memory_order_relaxed) == 10) /* assert B */
  1. To understand std::memory_order_relaxed , you need to understand data dependency .要了解std::memory_order_relaxed ,您需要了解数据依赖性 Clearly, x & y does not have any dependency to each other.显然, x & y彼此没有任何依赖关系。 So compiler may change the order of execution for thread 1 , unlike std::memory_order_seq_cst , where y.store(20) MUST executed before x.store(10) happens.因此编译器可能会更改线程 1的执行顺序,这与std::memory_order_seq_cst不同,其中y.store(20)必须x.store(10)发生之前执行。
    Let's see how each assertion may fail.让我们看看每个断言是如何失败的。 I've added tag for each instruction.我为每条指令添加了标签。

    assert A : 1-2 → 2-1 → assert A FAILED断言 A : 1-2 → 2-1 →断言 A FAILED
    assert B : See post for detailed answer.断言 B :请参阅帖子以获取详细答案。

    In short summary, thread 3 may see final updated variable y and get 10, but not the side-effect of 1-2 .简而言之,线程 3可能会看到最终更新的变量 y并获得 10,但不是1-2的副作用。 Even tho thread 2 must have seen it's side-effect in order to store 10 into y, compiler does not guarantee instruction's side effect must have synchronized between threads( happens-before )即使线程 2必须看到它的副作用以便将 10 存储到 y 中,编译器也不保证指令的副作用必须在线程之间同步(发生之前
    On the other hand, below example from the page is example of instruction's order preserved when instructions have data dependency.另一方面,页面中的以下示例是指令具有数据依赖性时保留指令顺序的示例。 assert(y <= z) is guaranteed to be passed. assert(y <= z)保证通过。
-Thread 1-
x.store (1, memory_order_relaxed)
x.store (2, memory_order_relaxed)

-Thread 2-
y = x.load (memory_order_relaxed)
z = x.load (memory_order_relaxed)
assert (y <= z)

2-2. 2-2。 is it that reordering will be done by compiler that value of y may not be updated even though y.store() is called?是否重新排序将由编译器完成,即使调用 y.store() 也可能不会更新 y 的值?
NO . As I've described in 2., it means compiler may change the order of instructions that does not have data dependency.正如我在 2. 中所描述的,这意味着编译器可能会更改不具有数据依赖性的指令顺序。 Of course y must be updated when y.store() is called.当然,在y.store()时必须更新y After all, that's the definition of atomic instruction.毕竟,这是原子指令的定义。

Assuming 'x' and 'y' are initially 0:


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

 -Thread 2-
 x.store (10, memory_order_release);

 -Thread 3-
 assert (y.load (memory_order_acquire) == 20 && x.load (memory_order_acquire) == 0)

 -Thread 4-
 assert (y.load (memory_order_acquire) == 0 && x.load (memory_order_acquire) == 10)
  1. Consistent mode requires happens-before relationship to all data.一致模式需要与所有数据发生先行关系。 So under consistent mode, y.store() must happens-before x.store() or vice versa.所以在一致模式下, y.store()必须发生在x.store()之前,反之亦然。
    If thread 3 's assert gets passed, it means y.store() happened before x.store() .如果线程 3的断言通过,则意味着y.store()发生在x.store()之前。 So thread 4 must have seen y.load() == 20 before x.load() == 10 .所以线程 4必须在x.load() == 10之前看到y.load() == 20 Therefore assert is failed.因此断言失败。 Same thing happens if thread 4 's assert gets passed.如果线程 4的断言通过,也会发生同样的事情。
    acquire / release memory model does not enforce happens-before relationship to independent variables. acquire / release memory model 不强制与自变量发生先行关系。 So below order can be made without violating any rules.因此可以在不违反任何规则的情况下进行以下命令。
    thread 4 y.load()thread 1 y.store()thread 3 y.load()thread 3 x.load()thread 4 x.load()线程 4 y.load()线程 1 y.store()线程 3 y.load()线程 3 x.load()线程 4 x.load()
    Resulting both assertion gets passed.结果两个断言都通过了。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM