2015-10-06 52 views
2

通常認爲靜態初始化是線程安全的。保證只發生一次。然而,我很好奇在語言規範中哪些地方會出現可見性問題? 這來自http://www.ibm.com/developerworks/library/j-jtp03304/語言規範中的Java靜態初始化線程安全保證

這個過程保證當一個變量由一個線程由相同的監視器,在寫保護的同步塊期間由給定的顯示器的保護,通過另一個線程讀出的同步塊期間寫入該變量將被閱讀線程看到。在沒有同步的情況下,JMM不保證這一保證

我已經從幾個其他來源讀到類似的東西。在靜態初始化的情況下,我們不使用任何同步。假設初始化的資源是有效的不可變的,我們永遠不會寫入,所以不會有同步用於訪問它,也不會使其變得不穩定。那麼保證來自哪裏,任何閱讀線程都不會看到空指針或部分初始化對象?顯然,由於它在加載過程中發生,所以另一個線程不可能在之前讀取該值並且看到一個陳舊的值,但是確保初始化結果不會保留在執行線程的本地內存中?我好奇讀靜態初始化是安全的原因。

編輯:我明白靜態初始化是線程安全的。問題是爲什麼和什麼保證。

+0

似乎http://stackoverflow.com/q/878577/2078908 – ursa

+1

@ursa重複:我不這麼認爲 - 這是更一般(和不明確)的「線程安全」。這是特別談論類初始化和內存模型的交互。 「內存模型」這個詞甚至不會發生在這篇文章中。一個答案提到了 - 在此之前,但沒有解釋爲什麼*初始化發生 - 在任何其他事情之前,就規格而言。我認爲這是一個單獨的問題。 –

回答

6

我相信這實際上是JLS 12.4.2中的類初始化規則的結果。這涉及在鎖上進行同步,只有在執行靜態初始化程序和字段初始化程序後才釋放它。那鎖獲取和釋放然後通過JLS 17.4.4影響線程模型的「發生之前」部分(我認爲 - 我不是這方面的專家)。

注意12.4.2狀態:

的實現可以通過eliding步驟1中的鎖獲取優化該過程(在步驟4/5釋放),當它能夠確定類的初始化已經完成了,只要在內存模型方面,所有發生在之前,如果獲得鎖定,將存在的排序,在執行優化時仍然存在。

相關問題