Synchronized可重入鎖分析

可重入鎖又稱遞歸鎖,是指在同一個線程在外層方法獲取鎖的時候,再進入該線程的內層方法會自動獲取鎖(前提是鎖對象必須是同一對象或者class),iphone

不會由於以前已經獲取過還沒實方而發生阻塞。即同一線程可執行多個持有同一個鎖的方法。spa

先來一段代碼:線程

public class ReentrantSynchronized {
    public synchronized void firstIPhoneByElectric() {
        System.out.println("第一部iphone充電..." + Thread.currentThread().getName());
        secondIPhoneByElectric();
    }

    public synchronized void secondIPhoneByElectric() {
        System.out.println("第二部iphone充電..." + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        ReentrantSynchronized reentrantSynchronized = new ReentrantSynchronized();
        reentrantSynchronized.firstIPhoneByElectric();
    }

}

就像一個多用充電線能夠同時給多部iphone充電,可是不會發生任何衝突和阻塞,也就是第一部iphone能夠獲取充電線(鎖)充電的同時還能夠第二部iphone也能夠獲取充電線(鎖)進行充電。code

執行結果以下:對象

 

 

 在上面的代碼中,類中的兩個方法都被內置鎖synchronized修飾,給第一部手機充電的同時(firstIPhoneByElectric方法中)給第二部手機充電(調用了secondIPhoneByElectric方法)。blog

由於充電線時多用的(synchronized是可重入的),因此同一我的給第二部手機充電時能夠直接用該多用充電線進行充電(在同一線程在調用secondIPhoneByElectric時能夠直接得到遞歸

當前對象的鎖,進入secondIPhoneByElectric進行操做)。ip

設想:該充電線是單用的(若是synchronized不是可重入的),那麼給第二部手機充電時必須等到第一部手機充電完成釋放充電線後才能進行(當前線程在調用secondIPhoneByElectricget

以前必須將firstIPhoneByElectric獲取的鎖釋放掉),實際上該充電線已經被第一部手機佔用,且沒法釋放,(該對象鎖被當前線程所持有,且沒法釋放),因此此時會出現死鎖。同步

這是什麼原理呢?

當線程嘗試獲取鎖時,可重入鎖先嚐試獲取並更新status值,若是status == 0表示沒有其餘線程在執行同步代碼,則把status置爲1,當前線程開始執行。若是status != 0,

則判斷當前線程是不是獲取到這個鎖的線程,若是是的話執行status+1,且當前線程能夠再次獲取鎖。而非可重入鎖是直接去獲取並嘗試更新當前status的值,若是status != 0

的話會致使其獲取鎖失敗,當前線程阻塞。

釋放鎖時,可重入鎖一樣先獲取當前status的值,在當前線程是持有鎖的線程的前提下。若是status-1 == 0,則表示當前線程全部重複獲取鎖的操做都已經執行完畢,

而後該線程纔會真正釋放鎖。而非可重入鎖則是在肯定當前線程是持有鎖的線程以後,直接將status置爲0,將鎖釋放。

相關文章
相關標籤/搜索