【小知識探究系列四】synchronized的加鎖原理和膨脹過程探究(以64位jvm爲例)

一、synchronized加鎖原理

由於synchronized總體的工作原理是通過操作對象頭來實現加鎖和解鎖,因此在具體的瞭解synchronized之前,首先需要簡單瞭解一下對象頭。
所謂對象頭其實是每個對象都存在的一份存儲當前對象gc分代年齡、hashcode、鎖標記、當前獲取到鎖的線程ID等信息的一塊內存區域。對象頭主要分爲以下三塊:

1.Mark Word
2.指向類的指針
3.數組長度(只有數組對象纔有)

synchronized在加鎖過程中主要對mark word進行操作,因此主要對mark word的劃分,各個劃分快存儲的內容進行探索。如下圖所示mark word的劃分以及各個劃分塊存儲的內容:
在這裏插入圖片描述
在64位jvm中mark word的長度爲64bit,從圖中我們可以看出最後兩位用來作爲鎖標記位,在無鎖和偏向鎖狀態時還存在1bit的偏向鎖位用來標記是否是可偏向的。
我們可以使用jol來查看對象頭信息,要是有jol需要引入如下包:


<dependency>
      <groupId>org.openjdk.jol</groupId>
      <artifactId>jol-core</artifactId>
      <version>0.8</version>
    </dependency>

執行以下代碼我們可以簡單看一下對象頭信息:

        Object o=new Object();
        System.out.println(VM.current().details());
        System.out.println(ClassLayout.parseInstance(o).toPrintable());

執行結果:
在這裏插入圖片描述
從執行結果我們可以看到對象頭總共佔了96bit【空框1】,其中mark Word佔了64bit【紅框2】,最後三位的狀態爲001說明當前處於無鎖狀態。
從上邊我們知道了synchronized在加鎖解鎖時操作的內存空間,那麼synchronized是如何操作的,在什麼時候進行操作,操作了什麼內容呢,下文將進一步瞭解。
使用javap反編譯工具對含有synchronized代碼塊的代碼進行反彙編,執行javap -v App.class的運行結果:
在這裏插入圖片描述
可以看到在被synchronized包起來的代碼塊前後增加了monitorenter和monitorexit兩條彙編指令,當代碼執行到monitorenter指令時開始加鎖操作,大概執行過程如下:





在代碼進入代碼塊的時候,如果此同步對象沒有被鎖定(鎖標誌位爲“01”狀態),虛擬機首先將在當前線程的棧幀中建立一個名爲Lock Record的空間,用於存儲鎖對象目前的Mark Word的拷貝,然後,虛擬機將使用CAS操作嘗試將對象的Mark Word更新爲Lock Record的指針。如果這個更新動作成功了,那麼這個線程就擁有了該對象的鎖,並且隊形Mark Word的鎖標誌位(Mark Word的最後兩個bits)將轉變爲‘00’,即表示此對象處於輕量級鎖定的狀態。
—深入理解JVM

二、synchronized鎖膨脹過程

鎖膨脹是從偏向鎖—>輕量級鎖---->重量級鎖的轉換過程。在探究膨脹過程之前,我們先簡單瞭解一下偏向鎖、輕量級鎖、重量級鎖的概念。
①重量級鎖:傳統重量級鎖指使用操作系統互斥量來實現加鎖(PV操作),使用這種鎖的話,即使沒有所競爭的時候還是會調用操作系統級別的互斥量實現加鎖,造成性能消耗。

②輕量級鎖:通過簡單的數據操作實現加鎖,不需要調用OS級別的加鎖機制。

*在當前線程自己的棧區創建Lock Record用於存儲Object的Mark Word的拷貝

*將Mark Word副本存入lock record

*基於CAS的機制將Object的Mark Word跟新爲執行Lock record的指針

*如果CAS跟新成功,則當前線程獲取到鎖,否則檢查Mark Word出的指針是否指向自己的棧針

*如果指向自己的棧針,則說明已經獲取到鎖,則重入代碼快執行,否則說明鎖已經被佔用,則膨脹爲重量級鎖
③偏向鎖:偏向鎖可以說是在輕量級鎖上的進一步優化,輕量級鎖在沒有鎖競爭的條件下還需要執行CAS操作,偏向鎖連CAS都不操作。所謂“偏”就是說偏袒於第一次獲得鎖的線程,如果在接下來的執行過程中,該鎖沒有被其他的線程獲取,則持有偏向鎖的線程將不需要執行同步操作,直接獲得運行資源。直到另外一個線程到來,偏向鎖開始膨脹。

1.配置虛擬機開啓偏向鎖

-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章