簡體   English   中英

引擎蓋下的java中的易失性關鍵字

[英]Volatile keyword in java under the hood

我和老師討論過java中的volatile關鍵字。 說變量被聲明為volatile時是否正確:

該變量的值永遠不會被線程本地緩存:所有讀取和寫入將直接進入“主存儲器”。

我老師的意見是:

volatile關鍵字保證變量的值將保存在主內存中。

有人能解決我們的沖突嗎? 謝謝!

有關volatile等關鍵字的確切含義,請查看Java語言規范以查看官方含義。

JLS第8.3.1.4段解釋了volatile含義:

字段可以聲明為volatile,在這種情況下,Java Memory Model可以確保所有線程都看到變量的一致值(第17.4節)。

第17.4節解釋了Java內存模型。 內存模型為您提供有關程序中每個語句之后數據發生情況的某些保證。

如果仔細研究,你會發現volatile意味着如果你寫一個volatile變量,你可以保證其他線程會看到寫的內容。 故意沒有具體說明如何在實踐中實施。 它可以通過強制寫入主內存來實現,但JVM實現者可以自由選擇不同的,可能更有效的機制。

所以,嚴格來說,你的老師是對的。 它並不一定意味着將值寫入主存儲器; 雖然在實踐中可能就是這種情況 - 但這取決於特定的JVM實現。

volatile作用是忽略所有本地CPU緩存; 或者等效地刷新包含要從主存儲器刷新的volatile變量的高速緩存行。 因此,正如文檔所示,它確保所有讀取都直接從主存儲器讀取,並且所有寫入都直接進入主存儲器。

除此之外, volatile還具有原子操作保證。 它確保以此關鍵字為前綴的變量將被完整地讀取或寫入,就像它是單個指令一樣。 (相比之下,你不會擔心由2個線程寫入的64位長整數最后是來自一個線程的第一個32位和來自另一個線程的第二個32位。)因此在某些情況下例如如果在32位機器上使用64位長整數的volatile時,JVM可能需要做的不僅僅是“易失性”指令。 更多文檔位於https://blogs.oracle.com/dave/entry/java_memory_model_concerns_on

針對您的具體問題。

  • 在讀取Java中的volatile時,它確保變量的值來自主內存。
  • 在Java中編寫volatile時,它確保將變量的值寫入主內存。

說了上面的話 - 這是從“邏輯”的角度來看的。 實際上,現代CPU采用復雜的緩存策略,有時可以保證上述情況不會實際寫入主內存。 然而,它只能實現相同的效果才能絕對實現作為性能優化步驟。 但我認為這超出了討論的范圍。

我將引用文檔中的兩段

第一

字段可以聲明為volatile,在這種情況下,Java Memory Model可以確保所有線程都看到變量的一致值(第17.4節)。

第二

內存模型描述了程序的可能行為。 只要程序的所有結果執行產生可由內存模型預測的結果,實現就可以自由地生成它喜歡的任何代碼。

這為實現者提供了大量的自由來執行無數的代碼轉換,包括重新排序動作和刪除不必要的同步。


現在,如果您將參考大多數關於votatile keyword in java的教程, votatile keyword in java大多數教程都會提出與您建議的相同的東西,即, 此變量的值永遠不會被線程本地緩存:所有讀取和寫入都將直接進行到“主要記憶”

但是文檔並不能保證它。 雖然它永遠不會否認它。 它只是說這是可能的行為

所以我會說你的老師是對的。 根據文檔(而不是比其他文檔的最教程)volatile關鍵字絕對答應,該變量的值將被保存在主存儲器。

但是,這不會讓你錯,這一切都取決於JVM的實現。

在這里: https//docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.4從Java 8 SE規范:

字段可以聲明為volatile,在這種情況下,Java Memory Model可確保所有線程都看到變量的一致值

它在“Java Concurrency in Practice”中描述了非常好的IMHO。 https://jcip.net/也許你的圖書館里有它?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM