可重入鎖又稱遞歸鎖,是指在同一個線程在外層方法獲取鎖的時候,再進入該線程的內層方法會自動獲取鎖(前提是鎖對象必須是同一對象或者class),
不會因為之前已經獲取過還沒實方而發生阻塞。即同一線程可執行多個持有同一個鎖的方法。
先來一段代碼:
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也可以獲取充電線(鎖)進行充電。
執行結果如下:

在上面的代碼中,類中的兩個方法都被內置鎖synchronized修飾,給第一部手機充電的同時(firstIPhoneByElectric方法中)給第二部手機充電(調用了secondIPhoneByElectric方法)。
因為充電線時多用的(synchronized是可重入的),所以同一個人給第二部手機充電時可以直接用該多用充電線進行充電(在同一線程在調用secondIPhoneByElectric時可以直接獲得
當前對象的鎖,進入secondIPhoneByElectric進行操作)。
設想:該充電線是單用的(如果synchronized不是可重入的),那么給第二部手機充電時必須等到第一部手機充電完成釋放充電線后才能進行(當前線程在調用secondIPhoneByElectric
之前必須將firstIPhoneByElectric獲取的鎖釋放掉),實際上該充電線已經被第一部手機占用,且無法釋放,(該對象鎖被當前線程所持有,且無法釋放),所以此時會出現死鎖。
這是什么原理呢?
當線程嘗試獲取鎖時,可重入鎖先嘗試獲取並更新status值,如果status == 0表示沒有其他線程在執行同步代碼,則把status置為1,當前線程開始執行。如果status != 0,
則判斷當前線程是否是獲取到這個鎖的線程,如果是的話執行status+1,且當前線程可以再次獲取鎖。而非可重入鎖是直接去獲取並嘗試更新當前status的值,如果status != 0
的話會導致其獲取鎖失敗,當前線程阻塞。
釋放鎖時,可重入鎖同樣先獲取當前status的值,在當前線程是持有鎖的線程的前提下。如果status-1 == 0,則表示當前線程所有重復獲取鎖的操作都已經執行完畢,
然后該線程才會真正釋放鎖。而非可重入鎖則是在確定當前線程是持有鎖的線程之后,直接將status置為0,將鎖釋放。

