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其他線程才能獲得鎖,因而,不可中斷性實現。

另外,有的面試題會問非同步方法和同步方法同時調用會不會同步執行,答案是不會。

因為,非同步方法執行時不會去考慮線程進入數以及獲得鎖一系列流程,直接開始執行,怎么可能同步執行呢


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM