2017-02-11 113 views

回答

9

由於xy均爲零,由C++標準中定義的抽象機不能寫入任一存儲器的位置,所以這可能是一個問題的唯一方法是,如果執行決定寫入到存儲器位置反正。例如,如果它轉化

if (x) y = 1; 

y = 1; 
if (!x) y = 0; 

這是根據作爲-如果因爲任何一個線程的觀察到的行爲的規則是相同的(C++ 14 1.9潛在有效重寫[intro.execution])

該國際標準中的語義描述定義了一個參數化的非確定性抽象 機器。本國際標準沒有要求符合實施的結構。 特別是,他們不需要複製或模擬抽象機器的結構。相反,需要遵守 實現來模擬(僅)抽象機器的可觀察行爲,如下面解釋的 。

這實際上在C++ 11之前是有效的重寫,但是自從C++ 11開始考慮執行線程之後。因此,只要沒有數據競爭發生在抽象機器中,就不允許實現進行更改,以便跨線程觀察到不同的行爲。

在C++ 14標準中有一個特別註釋,它適用於此(C++ 14 1.10 [into。多線程]段落22)

[注:編譯器變換該引進分配到一個潛在的共享存儲器位置的是 不會被抽象機被修改通常由該標準排除,因爲這種 分配可能會覆蓋另一在執行抽象機器時不會遇到數據競爭的情況下由不同線程分配。 ...

因此,重寫無效。該實現必須保留所觀察到的行爲,即使在線程間也不會修改xy。因此,沒有數據競賽。

13

這兩個線程都不會寫入,因爲這兩個變量在條件之前都不爲零。

11

數據競賽不是您的代碼的靜態屬性。它們是執行時程序實際狀態的屬性。所以雖然該程序可能是處於代碼會產生數據競爭的狀態,但這不是問題。

問題是,考慮到系統的狀態,代碼是否會導致數據競爭?由於程序處於這樣一種狀態,即任何線程都不會寫入任何變量,因此代碼不會導致數據競爭。

數據競賽不是你的代碼可能做的。這是關於他們會做什麼。就像一個接受指針的函數不是未定義行爲一樣,因爲它使用指針而不檢查NULL。如果有人傳遞了一個真正爲NULL的指針,那只有UB。

2

我發現這篇文章由Hans-J撰寫。波姆照明:
http://www.hpl.hp.com/techreports/2009/HPL-2009-259html.html#races

我們說兩個普通存儲器操作衝突,如果他們訪問 同一存儲器位置(例如,可變或數組元素),和在他們的 至少一個寫入地點

我們說一個程序允許在一組特定的輸入 數據競爭,如果有一個順序一致的執行,即各個線程的操作的 交織,其中兩個 發生衝突操作可以同時「執行」。對於我們的 目的,如果 它們在交錯中彼此緊挨着並且對應於不同的線程,則可以「同時」執行兩個這樣的操作。

而且文章接着我們的觀點:

我們的數據競爭的定義是相當嚴格的:必須有執行原來的,未轉換的程序的 實際的方式,使得 衝突操作並行發生。這給編譯器帶來了負擔,不會通過引入有害的數據競爭來「破壞」程序。

正如文章,報告了同樣的例子(及其他)中所述: 有這個程序沒有順序一致的執行中,線程1個受讓人爲y因爲x和y不會成爲非零 。事實上,你永遠不會滿足條件,所以沒有人寫信給另一個線程可能正在閱讀的變量。

要了解與將數據種族存在的情況下的差異,試着想想文章下面的例子:

y = ((x != 0)? 1 : y) # Thread 1 
y = 2;     # Thread 2 

在很顯然最後這種情況下,可以發生Y是分配(寫)由線程1執行,而線程2執行時y = 2;y由線程1寫入,無論如何)。數據競賽可能發生。

0

如果未設置x,則不會將y設置爲1,反之亦然。所以,這裏的事情確實是順序發生的。

相關問題