synchronized底層原理
- 2021 年 5 月 24 日
- 筆記
- JAVA, synchronized, 多執行緒, 面試題總結
synchronized底層原理
通過反編譯class文件,可以看到synchronized最關鍵的部分是monitor對象。
又因為synchronized關鍵字使用的方法不同,可以將monitor對象使用分為以下兩種情況。
-
synchronized放在方法簽名上
public synchronized void method(){ }
這時候在反編譯文件里,該方法的ACC_SYNCHRONIZED訪問標誌位會被標記
-
synchronized作為對象鎖
public void method(){ synchronized(new Object()){ } }
這時候ACC_SYNCHRONIZED並不會被標記,但是會執行monitorenter和monitorexit命令,從而實現同步。
- 可以看到雖然只有一個monitorenter但是有兩個monitorexit,這是因為有兩種情況可以讓當前執行緒放棄鎖,即
- 當前synchronized程式碼塊運行完
- 發生中斷
monitor對象
其實以上兩種方法都是相同的,ACC_SYNCHRONIZED標誌位是隱式調用了monitor對象而已。下面來說一下monitor對象以及它是如何實現運作的。
monitor的數據結構
關於存儲的monitor對象有以下三種可能,對應不同的synchronzied使用方式,
-
synchronzied修飾普通方法——>鎖的是this,也就是調用當前方法的實例對象
-
synchronized修飾程式碼塊——>鎖的是synchronized後面括弧里的方法
-
synchronized修飾static方法——>鎖的是類的.class對象
關於面試的時候會問的各種情況下會不會同步執行,牢記一點
鎖的對象相同才會同步執行
鎖的對象相同才會同步執行
鎖的對象相同才會同步執行
也就是說,類鎖對普通方法鎖是不存在覆蓋的,下面兩個方法不會同步執行
public synchronized void method1(){ } public static synchronized void method2(){ }
monitor運行機制
如果一個執行緒運行到一個同步程式碼塊,如果執行緒進入數為0,則該執行緒可擁有此monitor對象的鎖,遇到monitorenter,進入數+1,遇到monitorexit,進入數-1。
如果目前執行緒進入數不為0,則當前執行緒不能獲得此monitor對象的鎖,需要等待。
synchronized的可重入性,不可中斷性是如何保障的呢?
monitor對象的執行緒進入數不是0和1,如果發生重入,進入數+1即可。
不可中斷性:一個執行緒獲取鎖後,其他執行緒必須阻塞或等待,不能搶佔,按照上面的運行機制,必須執行緒進入數=0其他執行緒才能獲得鎖,因而,不可中斷性實現。
另外,有的面試題會問非同步方法和同步方法同時調用會不會同步執行,答案是不會。
因為,非同步方法執行時不會去考慮執行緒進入數以及獲得鎖一系列流程,直接開始執行,怎麼可能同步執行呢