簡體   English   中英

C++ 原子獲取/釋放操作的實際含義

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

我正在瀏覽頁面並試圖了解 Memory model 同步模式。 在下面從那里提取的示例中:

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

到哪個聲明在線程 1 中存儲到“y”之前發生到“x”的存儲。這里的“y”變量是普通全局變量還是原子變量?

此外,如果線程 2 中 'x' 的加載獲得線程 1 中發生的存儲的結果,則它必須全部看到線程 1 中存儲之前發生的所有操作,甚至是不相關的操作。

那么 x.store() 操作意味着所有對 memory 的讀/寫都應該更新相應的 memory 數據值是什么意思?

然后對於 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 類似於順序一致模式,只是它只對因變量應用 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)

用明確的術語來說是什么意思?

 -Thread 1-       -Thread 2-
 y = 1            if (x.load() == 2)
 x.store (2);        assert (y == 1)
  1. 自然地,編譯器可能會更改不依賴於提高性能的操作順序。
    但是當std::memory_order_seq_cst 起作用時,任何原子運算符都作為memory barrier工作。
    這並不意味着變量 y是原子變量,編譯器只是保證y = 1; 發生在x.store (2); . 如果有另一個線程 3操作變量 y ,斷言可能會由於另一個線程而失敗。
    如果我的解釋很難理解(由於我的英語不好......)請檢查memory barrier & happened-before
    如果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. 要了解std::memory_order_relaxed ,您需要了解數據依賴性 顯然, x & y彼此沒有任何依賴關系。 因此編譯器可能會更改線程 1的執行順序,這與std::memory_order_seq_cst不同,其中y.store(20)必須x.store(10)發生之前執行。
    讓我們看看每個斷言是如何失敗的。 我為每條指令添加了標簽。

    斷言 A : 1-2 → 2-1 →斷言 A FAILED
    斷言 B :請參閱帖子以獲取詳細答案。

    簡而言之,線程 3可能會看到最終更新的變量 y並獲得 10,但不是1-2的副作用。 即使線程 2必須看到它的副作用以便將 10 存儲到 y 中,編譯器也不保證指令的副作用必須在線程之間同步(發生之前
    另一方面,頁面中的以下示例是指令具有數據依賴性時保留指令順序的示例。 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。 是否重新排序將由編譯器完成,即使調用 y.store() 也可能不會更新 y 的值?
正如我在 2. 中所描述的,這意味着編譯器可能會更改不具有數據依賴性的指令順序。 當然,在y.store()時必須更新y 畢竟,這是原子指令的定義。

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. 一致模式需要與所有數據發生先行關系。 所以在一致模式下, y.store()必須發生在x.store()之前,反之亦然。
    如果線程 3的斷言通過,則意味着y.store()發生在x.store()之前。 所以線程 4必須在x.load() == 10之前看到y.load() == 20 因此斷言失敗。 如果線程 4的斷言通過,也會發生同樣的事情。
    acquire / release memory model 不強制與自變量發生先行關系。 因此可以在不違反任何規則的情況下進行以下命令。
    線程 4 y.load()線程 1 y.store()線程 3 y.load()線程 3 x.load()線程 4 x.load()
    結果兩個斷言都通過了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM