文章目錄
volatile在JVM內存交互中的操作
只是做一個簡單的記錄 ^_^
JMM
- 主內存(共享): 本地方法區 + 堆
- 工作內存(線程私有): 棧 + 寄存器(程序計數器 + CPU高速緩存區)
- 幾個規則:
- 所有變量都會存在主內存中,工作內存會保存其中部分變量的拷貝
- 線程對變量的操作必須在工作內存中進行,不能直接讀寫主內存的變量
- 不同線程的工作內存是私有的,不能相互直接訪問,必須通過主內存傳遞
- 示意圖
JVM內存交互操作
- JVM定義了8種操作(原子)來完成主內存與工作內存之間的交互
- read: 讀取,將變量從主內存傳到工作內存,接着將執行load
- load: 載入,將read操作拿到的變量放到工作內存的變量
- use: 使用,將工作內存的變量傳給執行引擎
- assign: 賦值,將執行引擎得到的值賦值給工作內存的變量
- store: 存儲,將工作的內存變量的值傳到主內存中,接着將執行write
- write: 寫入,將store操作拿到變量放到主內存的變量
- lock: 鎖定,將主內存變量標識爲線程獨佔狀態
- unlock: 解鎖,將主內存變量解除線程獨佔狀態,其後可以被其他線程鎖定
volatile在其中的操作
- volatile會觸發lock/unlock,在硬件層的操作流程大致如下
- lock -> 鎖住主內存變量a,當前線程獨佔
- 變量a -> store進入主內存 -> wirte給主內存的變量a
- unlock -> 解除獨佔狀態
- lock操作會觸發MESI緩存一致性協議:CPU總線嗅探機制被觸發 -> 其他線程的該變量a失效 -> 其他線程重新從主內存獲取變量a
示例-非volatile修飾的變量賦值操作
- 代碼示例
private static int a = 10; public static void main(String[] args) { new Thread(() -> { a = 15; }).start(); }
- 示意圖
-------主內存---------|-------工作內存---------|---------CPU-------- a=10 --read-->--load--> a=10 --use--> 計算 a=15 <--assign-- a=15 <--write--<--store--
示例-volatile修飾的變量賦值操作(lock/unlock)
- 代碼示例
private static volatile int a = 10; public static void main(String[] args) { new Thread(() -> { a = 15; }).start(); }
- 示意圖
-------主內存---------|-------工作內存---------|---------CPU-------- a=10 --read-->--load--> a=10 --use--> 計算 a=15 <--assign-- -------------lock------------ a=15 <--write--<--store-- ------------unlock-----------