切換語言為:簡體
透徹講解 Java synchronized 底層實現原理

透徹講解 Java synchronized 底層實現原理

  • 爱糖宝
  • 2024-07-31
  • 2063
  • 0
  • 0

synchronized 是 Java 中最基本的鎖機制,使用它可以實現對共享資源的互斥訪問。當一個執行緒訪問被 synchronized 修飾的方法或程式碼塊時,它會自動獲取鎖,其他執行緒只能排隊等待該執行緒釋放鎖。

# 底層實現—監視器

想要了解 synchronized 的底層實現,需要從 synchronized 生成的位元組碼說起,比如以下程式:

public class App {
    public static void main(String[] args) {
        synchronized (App.class) {
            System.out.println("Hello World!");
        }
    }}

它的位元組碼如下:

透徹講解 Java synchronized 底層實現原理

從上述結果可以看出,在 main 方法中多了一對 monitorenter 和 monitorexit 的指令,它們的含義是:

  • monitorenter:表示進入監視器;

  • monitorexit:表示退出監視器。

由此可知 synchronized 的底層是透過 Monitor(監視器)實現的。

# 監視器具體實現

在 HotSpot 虛擬機器中,監視器 Monitor 底層是由 C++實現的,它的實現物件是 ObjectMonitor。ObjectMonitor 結構體的實現原始碼如下:

ObjectMonitor::ObjectMonitor() {  
  _header       = NULL;  
  _count       = 0;  
  _waiters      = 0,  
  _recursions   = 0;       //執行緒的重入次數
  _object       = NULL;  
  _owner        = NULL;    //標識擁有該monitor的執行緒
  _WaitSet      = NULL;    //等待執行緒組成的雙向迴圈連結串列,_WaitSet是第一個節點
  _WaitSetLock  = 0 ;  
  _Responsible  = NULL ;  
  _succ         = NULL ;  
  _cxq          = NULL ;    //多執行緒競爭鎖進入時的單向連結串列
  FreeNext      = NULL ;  
  _EntryList    = NULL ;    //_owner從該雙向迴圈連結串列中喚醒執行緒結點,_EntryList是第一個節點
  _SpinFreq     = 0 ;  
  _SpinClock    = 0 ;  
  OwnerIsThread = 0 ;  }

在以上程式碼中有幾個關鍵的屬性:

  • _count:記錄該執行緒獲取鎖的次數(也就是前前後後,這個執行緒一共獲取此鎖多少次)。

  • _recursions:鎖的重入次數。

  • _owner:The Owner 擁有者,是持有該 ObjectMonitor(監視器)物件的執行緒;

  • _EntryList:EntryList 監控集合,存放的是處於阻塞狀態的執行緒佇列,在多執行緒下,競爭失敗的執行緒會進入 EntryList 佇列。

  • _WaitSet:WaitSet 待授權集合,存放的是處於 wait 狀態的執行緒佇列,當執行緒執行了 wait() 方法之後,會進入 WaitSet 佇列。

監視器執行的流程是這樣的:

  1. 執行緒透過 CAS(對比並替換)嘗試獲取鎖,如果獲取成功,就將 _owner 欄位設定為當前執行緒,說明當前執行緒已經持有鎖,並將 _recursions 重入次數的屬性 +1。如果獲取失敗則先透過自旋 CAS 嘗試獲取鎖,如果還是失敗則將當前執行緒放入到 EntryList 監控佇列(阻塞)。

  2. 當擁有鎖的執行緒執行了 wait 方法之後,執行緒釋放鎖,將 owner 變數恢復爲 null 狀態,同時將該執行緒放入 WaitSet 待授權佇列中等待被喚醒。

  3. 當呼叫 notify 方法時,隨機喚醒 WaitSet 佇列中的某一個執行緒,當呼叫 notifyAll 時喚醒所有的 WaitSet 中的執行緒嘗試獲取鎖。

  4. 執行緒執行完釋放了鎖之後,會喚醒 EntryList 中的所有執行緒嘗試獲取鎖。

以上就是監視器的執行流程,執行流程如下圖所示: 

透徹講解 Java synchronized 底層實現原理

# 小結

synchronized 是透過 Monitor 監視器實現的,而監視器又是透過 C++ 程式碼實現的,它的具體執行流程是:執行緒先透過自旋 CAS 的方式嘗試獲取鎖,如果獲取失敗就進入 EntrySet(監控)集合,如果獲取成功就擁有該鎖。而擁有鎖的執行緒當呼叫 wait() 方法時,會釋放鎖並進入 WaitSet(待授權)集合,直到其他執行緒呼叫 notify 或 notifyAll 方法時纔會嘗試再次獲取鎖。執行緒正常執行完成之後,就會通知 EntrySet 集合中的執行緒,讓它們嘗試獲取鎖。

# 參考資料

www.cnblogs.com/freelancy/p/15625602.html

blog.csdn.net/qq_43783527/article/details/114669174

www.cnblogs.com/hongdada/p/14513036.html

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.