1

我正在用C編寫一個程序。爲了簡單起見說:有很多變量,許多線程都可以讀取和寫入。每次寫入它們時,都會通過原子交換(GCC原子操作,同步和交換)進行寫入。每次讀取其中一個變量時,是否需要使用原子加載?還是原子寫入足以避免在數據寫入過程中讀取數據?C原子操作,如果寫入都是原子交換,我需要原子加載嗎?

注意,任何地方,需要從這些瓦爾第一張價值的一個使用數據:

int success = 0; 
while (!success) { 
    int x = shared_x; 
    ... work with x, result in y ... 
    success = cmp_swap(&shared_x, x, y); 
} 

我的問題不是關於比賽的數據,那就是我不擔心我可能會丟失數據。我擔心的是,shared_x的價值可能會在我閱讀的一半時發生變化。假設它是一個8字節的整數,這是否是一個潛在的問題:說shared_x是一個64位整數,8個字節。是否有可能我的x = shared_x將複製前4個字節,然後以原子方式寫入shared_x,然後此語句完成讀取第二個4字節。這將導致x包含舊值shared_x的前4個字節,以及新shared_x的最後4個字節。我懷疑原子交換(http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html - 使用__sync_bool_compare_and_swap)中的內存屏障足以防止這種情況發生......但我不確定。

回答

3

它看起來像你從shared_x閱讀,計算一些新的,然後寫回shared_x。您寫入shared_x的值似乎取決於您最初從中讀取的值。

如果是這種情況,那麼你在那裏有一個依賴關係,並且很可能不僅需要使原子讀取,而且還需要完成「讀取,計算,回寫」原子的整個操作。意思是說,你需要同步它。就像一個互斥體一樣。

我說「最有可能」,因爲我不知道如果我不知道代碼實際上做了什麼。您需要分析在線程A寫入shared_x的情況下發生的情況,而線程B當前正在根據舊值shared_x進行計算,然後將結果寫回到它。線程A寫入的值會永遠丟失。我不知道這是否會對您造成問題。只有你可以知道這一點。如果競爭條件是好的,那麼你不需要同步或使讀取原子。

如果你只是想確保從shared_x的閱讀不會讓你垃圾和不關心上述的競爭條件,那麼答案是「最有可能你不需要做閱讀原子。」而不是我複製粘貼&,你可以在這裏閱讀細節:

Atomicity in C++ : Myth or Reality

這些問題即使是C++,同樣擁有對C也是如此。

注意雖然原子現在也在C標準中(C11),由<stdatomic.h>標題和_Atomic類型限定符提供。但當然,並非所有編譯器都支持C11。

+0

更新了我的示例,現在它顯示了在計算新值時寫入內容時發生了什麼,它只是重新開始並重試。 – Exodist 2013-02-23 06:16:28

+0

@Exodist這裏需要的是整個程序,而不僅僅是它的一部分。你需要自己做分析。假設競爭條件並遵循程序邏輯。如果比賽條件完全沒有任何不良影響,那麼你很好。您也可以手動引入競賽條件並觀察。 – 2013-02-23 06:18:55

+0

我不能正確地問我的問題。我不關心工作的同步。我會在上面更新我的問題。 – Exodist 2013-02-23 06:24:29