volatile在JVM內存交互中的操作

volatile在JVM內存交互中的操作

只是做一個簡單的記錄 ^_^

JMM

  • 主內存(共享): 本地方法區 + 堆
  • 工作內存(線程私有): 棧 + 寄存器(程序計數器 + CPU高速緩存區)
  • 幾個規則:
    • 所有變量都會存在主內存中,工作內存會保存其中部分變量的拷貝
    • 線程對變量的操作必須在工作內存中進行,不能直接讀寫主內存的變量
    • 不同線程的工作內存是私有的,不能相互直接訪問,必須通過主內存傳遞
  • 示意圖
    JMM模型示意圖

JVM內存交互操作

  • JVM定義了8種操作(原子)來完成主內存與工作內存之間的交互
    • read: 讀取,將變量從主內存傳到工作內存,接着將執行load
    • load: 載入,將read操作拿到的變量放到工作內存的變量
    • use: 使用,將工作內存的變量傳給執行引擎
    • assign: 賦值,將執行引擎得到的值賦值給工作內存的變量
    • store: 存儲,將工作的內存變量的值傳到主內存中,接着將執行write
    • write: 寫入,將store操作拿到變量放到主內存的變量
    • lock: 鎖定,將主內存變量標識爲線程獨佔狀態
    • unlock: 解鎖,將主內存變量解除線程獨佔狀態,其後可以被其他線程鎖定

volatile在其中的操作

  • volatile會觸發lock/unlock,在硬件層的操作流程大致如下
    1. lock -> 鎖住主內存變量a,當前線程獨佔
    2. 變量a -> store進入主內存 -> wirte給主內存的變量a
    3. unlock -> 解除獨佔狀態
    4. 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-----------
    
發佈了143 篇原創文章 · 獲贊 52 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章