這裏是一個場景線程是如何工作的?
我們有兩個線程都訪問同一塊的代碼和代碼有一個變量,例如
INT一個= 200;
線程A輸入並將其值更改爲a = 300;
然後線程B訪問這個變量,線程B會得到200或300什麼?
這裏是一個場景線程是如何工作的?
我們有兩個線程都訪問同一塊的代碼和代碼有一個變量,例如
INT一個= 200;
線程A輸入並將其值更改爲a = 300;
然後線程B訪問這個變量,線程B會得到200或300什麼?
兩個線程不保證以任何固定順序執行; A中的任何操作都可以在B中的任何操作之前進行(前提是操作仍然在其自己的線程中順序流動)。
因此,如果沒有同步,A可能會在B訪問它之前或之後更改它的值。如果A在B之前改變它,那麼B看到300;否則,B會看到200.
或者線程B可能會改變值的前8位,那麼線程A寫入的全部價值,然後線程B寫入值的後8位,所以你最終從300前8位和低8來自200的位,即456。完全不是預期的值。道德=不信任線程去執行任何可以預測共享變量而不同步的東西。 –
如果您的線程同時訪問您的代碼段,它將根據jvm級別中的線程優先級來執行。我們無法保證哪個線程將訪問代碼。如果它是同步的,則線程B必須等到線程A釋放資源。
下面的狀態圖表描述了線程狀態。
Thread.sleep(milliseconds), Thread.sleep(milliseconds, nanoseconds);
關於你的榜樣,我們不知道什麼線程B將採取200或300。如果妳在同一時間啓動兩個線程,因爲你的方法將同步線程B應該看到200(在情況下,如果它會成爲第一名或第三名)。
上述執行的結果取決於一致性模型。
在順序一致性模型中,執行的結果是所有指令都以某種全局順序執行。在這種情況下,threadB將獲得價值300
然而,現代機器使用獨自在那裏所有的同步(內存柵欄指令)操作發生在一個全球性的順序較弱的一致性模型。
如果商店的ThreadA已經完成之後發生對threadB負載,threadB將獲得值= 300。這是由高速緩存一致性協議保證。 但是,如果threadB的加載指令出現在threadA的存儲之前/(與某些優化有關),則threadB中共享變量的值未定義。這將是總線操作中threadB的負載和threadA的存儲之間的競爭條件的結果。
由於編譯器優化線程可以緩存數據和第一線的變化可能不會被第二個線程可以看出。這就是「揮發性」用於共享數據,以避免在多線程環境
Addendum-嗯,我說的是跨線程變量的變化,而不是同步的知名度的問題。
@Nippey,你在Java中對'volatile'的陳述是完全錯誤的。 –
@nneonneo:古典失敗稱爲「先閱後讀」。刪除了原始評論。 – Nippey
要看什麼「然後」的意思。如果不使用同步,線程B可能會在線程A更改該值之前出現。 – nneonneo
加上由於內存障礙,線程B可能永遠不會「看到」300值。 – slushi
@ gd1:不完全。 JLS至少給出了關於線程如何與內存交互的一些指導(並且更新的規範實際上具有獨立於架構的內存模型)。 – nneonneo