volatile,中文意思是不穩定的、反復無常的,用來修飾變量,和多線程、并發有關系。
Java代碼在編譯后會變成Java字節碼,字節碼被類加載器加載到JVM里,JVM執行字節碼,最終需要轉化為匯編指令在CPU上執行。
在多線程并發編程中 synchronized 和 volatile 都扮演著重要的角色。volatile 是輕量級的 synchronized,它在多處理器開發中保證了共享變量的“可見性”。可見性的意思是當一個線程修改一個共享變量時,另外一個線程能讀到這個修改的值。如果 volatile 使用恰當的話,它比 synchronized 的使用和執行成本更低,因為它不會引起線程上下文的切換和調度。
volatile 是如何來保證可見性的呢?對 volatile 修飾的共享變量進行寫操作時,觀察其匯編指令可發現有一條Lock前綴的指令。這個指令在多核處理器下會引發兩件事情:
1)將當前處理器緩存行的數據寫回到系統內存。
2)這個寫回內存的操作會導致其他處理器的緩存無效。
為了提高處理速度,處理器不直接和內存進行通信,而是先將系統內存的數據讀到內部緩存(L1,L2,L3)后再進行操作,但操作完之后不知道何時會寫到內存。如果對 volatile 修飾的變量進行寫操作,JVM就會向處理器發送一條Lock前綴的指令,將這個變量所在緩存行的數據寫回到系統內存。但是,這個時候其他處理器緩存的值還是舊值,再執行計算操作就會有問題。所以,在多核處理器下,為了保證各個處理器的緩存一致,就會實現緩存一致性協議(MESI協議),每個處理器通過嗅探在總線上傳播的數據來檢查自己緩存的值是不是過期了,當處理器發現自己緩存行對應的內存地址被修改,就會將當前處理器緩存行設置為無效狀態,當處理器對這個數據進行寫操作時,會重新從系統內存中把數據讀到處理器緩存中。