2017/12/10
簡單的解釋: 在多執行緒的環境下,volatile
用於讓變數的讀和寫都在記憶體中執行。
因為每個執行緒都需將變數放在 CPU cache 才能做運算,所以要從記憶體中把所有可存取的變數複製一份副本到 CPU cache 以供運算時讀寫操作使用,此時就有可能因為某些運算造成 CPU cache 存的變數值和記憶體存的變數值不一致。volatile
可以保證變數的讀寫操作都在記憶體中執行,以確保在多個執行緒都可以取到最新的變數值。
換個說法,每個執行緒都有自己的堆疊,所以它可以存取自己的變數副本。當執行緒被建立時,它將所有可存取的變數複製到自己的記憶體中。volatile
關鍵字用於告訴 JVM 說:「注意,這個變數可以在其他執行緒中修改」。若沒有這個關鍵字,JVM 可以自由地進行一些最佳化,像是在某些執行緒中從不更新這些本地副本。volatile
會強制執行緒更新每個變數的原始值。volatile
關鍵字可以用在任何類型的變數,可以是 primitive 或 objects!
對於非 volatile
變數而言,JVM 並不能保證什麼時候把記憶體的變數值讀取到 CPU cache 中,以及何時把 CPU cache 的變數值寫入到記憶體中。
因此在多執行緒的環境下,有可能造成 Thread 1 將 counter 變數設為 7,但沒有馬上寫入到記憶體中,造成 Thread 2 取到 counter 之值仍為 0。
圖片來源
由於 volatile
變數的讀寫都是在記憶體中執行,所以比直接在 CPU cache 做變數讀寫來得慢。
不過比 synchronized
快,因為 synchronized
要等到寫資料的執行緒做完才能夠讀到資料。
除了效能比較慢之外,用 synchronized
有一個風險是,若正在讀取變數的執行緒因為某些原因臨時被暫停 (suspended) 的話,其他正在等待寫入同一個變數的執行緒會 陷入無限的等待 或 直到讀取變數的執行緒終於做完。
Java Volatile Keyword Explained by Example
Java Volatile Keyword
[译] Java Volatile 关键字详解