這是一個競爭條件嗎?雙線程的良性數據競態條件
class A {
int x;
update() {
x = 5;
}
retrieve() {
y = x;
}
}
如果被保持更新(),以及獲取()由沒有任何鎖兩個不同的線程被稱爲,因爲有在一個共享變量的兩次存取至少一個寫入,這可以被歸爲一種族條件。但是,這在運行時真的是一個問題嗎?
這是一個競爭條件嗎?雙線程的良性數據競態條件
class A {
int x;
update() {
x = 5;
}
retrieve() {
y = x;
}
}
如果被保持更新(),以及獲取()由沒有任何鎖兩個不同的線程被稱爲,因爲有在一個共享變量的兩次存取至少一個寫入,這可以被歸爲一種族條件。但是,這在運行時真的是一個問題嗎?
沒有鎖,三件事情可能發生:
y
得到的x
新值(5)。y
獲得舊值x
(最可能爲0)。int
不是原子的,則y
可以獲得任何其他值。在Java中,讀到一個int
是原子的,所以第三個選項不會發生。不保證其他語言的原子性。
隨着鎖定,前兩個選項也可以發生。
儘管如此,存在額外的挑戰,具體取決於內存模型。在Java中,如果寫入不同步,則可以任意延遲直到下一個同步點(塊的結尾或對volatile
字段的訪問)。同樣,讀取可以從前一個同步點(塊的開始或volatile
字段的訪問)任意緩存。這很容易導致由陳舊緩存引起的問題。最終的效果是,即使第一個選項應該可以發生第二個選項。
在Java中,總是使用volatile
以及可以從其他線程訪問的字段,否則您將面臨由內存訪問重新排序引起的難以調試的競爭條件。在使用類似於Java中的內存模型的其他語言中也適用相同的警告 - 您可能需要告訴編譯器不要執行這些優化。
在C++中,volatile不保證任何類型的同步或內存障礙。它所做的只是防止某些種類的優化。我聽說VC++無故地創建了一個內存屏障,但那不是標準。 –
@JiveDadson然後它不是真的等同於Java的'volatile'。重寫。 –
@JiveDadson另外,如果'volatile'關鍵字不能削減它,那麼我不知道會發生什麼。微軟編譯器確實保證這一點:http://msdn.microsoft.com/en-us/library/12a04hfd(v=vs.80).aspx –
什麼語言?或者它是一個語言不可知的問題? –
稱這種「良性」的總比賽就像稱老虎是一隻大貓。 –