2012-11-29 42 views
0

這是一個競爭條件嗎?雙線程的良性數據競態條件

class A { 
    int x; 

    update() { 
     x = 5; 
    } 

    retrieve() { 
     y = x; 
    } 
} 

如果被保持更新(),以及獲取()由沒有任何鎖兩個不同的線程被稱爲,因爲有在一個共享變量的兩次存取至少一個寫入,這可以被歸爲一種族條件。但是,這在運行時真的是一個問題嗎?

+0

什麼語言?或者它是一個語言不可知的問題? –

+1

稱這種「良性」的總比賽就像稱老虎是一隻大貓。 –

回答

2

沒有鎖,三件事情可能發生:

  1. y得到的x新值(5)。
  2. y獲得舊值x(最可能爲0)。
  3. 如果寫入int不是原子的,則y可以獲得任何其他值。

在Java中,讀到一個int是原子的,所以第三個選項不會發生。不保證其他語言的原子性。

隨着鎖定,前兩個選項也可以發生。

儘管如此,存在額外的挑戰,具體取決於內存模型。在Java中,如果寫入不同步,則可以任意延遲直到下一個同步點(​​塊的結尾或對volatile字段的訪問)。同樣,讀取可以從前一個同步點(​​塊的開始或volatile字段的訪問)任意緩存。這很容易導致由陳舊緩存引起的問題。最終的效果是,即使第一個選項應該可以發生第二個選項。

在Java中,總是使用volatile以及可以從其他線程訪問的字段,否則您將面臨由內存訪問重新排序引起的難以調試的競爭條件。在使用類似於Java中的內存模型的其他語言中也適用相同的警告 - 您可能需要告訴編譯器不要執行這些優化。

+0

在C++中,volatile不保證任何類型的同步或內存障礙。它所做的只是防止某些種類的優化。我聽說VC++無故地創建了一個內存屏障,但那不是標準。 –

+0

@JiveDadson然後它不是真的等同於Java的'volatile'。重寫。 –

+0

@JiveDadson另外,如果'volatile'關鍵字不能削減它,那麼我不知道會發生什麼。微軟編譯器確實保證這一點:http://msdn.microsoft.com/en-us/library/12a04hfd(v=vs.80).aspx –