Java synchronized實現原理深度剖析

2020-07-16 10:05:09
剛剛開始學習 Java 的時候,一遇到多執行緒的問題就簡單粗暴地使用 synchronized 關鍵字,對於當時的我們來說,synchronized 是多麼的神奇和強大呀!那個時候我們還給 synchronized 起了一個名字“同步”,它成了我們解決多執行緒問題百試不爽的良藥。

後來隨著學習的深入,我們知道 synchronized 是一個重量級鎖,相對於 Lock,顯得非常笨重,以至於我們認為它不是那麼的高效而慢慢摒棄它。隨著 Javs 6 對 synchronized 進行了各種優化,synchronized 並不會顯得那麼笨重了。

本節我們重點討論一下 synchronized 關鍵字的實現機制、Java 對 synchronized 進行了什麼優化、鎖優化機制、鎖的儲存結構和升級過程。

Java synchronized 實現原理

synchronized 可以保證方法或者程式碼塊在執行時,同一時刻只有一個方法可以進入到臨界區,同時它還可以保證共用變數的記憶體可見性。

Java 中每一個物件都可以作為鎖,這是 synchronized 實現同步的基礎:
  • 普通同步方法,鎖是當前範例物件;
  • 靜態同步方法,鎖是當前類的 class 物件;
  • 同步方法塊,鎖是括號裡面的物件。

當一個執行緒存取同步程式碼塊時,它首先是需要得到鎖才能執行同步程式碼,當退出或者丟擲異常時必須要釋放鎖,那麼它是如何來實現這個機制的呢?我們先來看下面一段 Java 程式碼:
public class SynchronizedTest {
    public synchronized void test1(){

    }

    public void test2(){
        synchronized (this){

        }
    }
}
為了分析 synchronize 的實現,我們需要利用 javap 工具檢視生成的 .class檔案(位元組碼檔案)資訊: