ReentrantLock與synchronized兩種鎖都具備可重入的特徵,其實是個很簡單的概念,可是不少人都是不看源碼硬解釋,致使問題變得玄乎。今天我就簡單的進行一下解釋,可重入實際上也就是當前獲取到鎖執行權限的線程,能夠屢次調用加鎖的過程,而不會影響線程的正常運行。測試
1、舉個例子spa
家裏只有一輛車,老大、老二須要使用的時候都要去老爸那兒拿鑰匙。線程
週一 ,老大:「老爸,給我鑰匙我要出去浪」,老爸給了他,後來老二又來要鑰匙,老爸說你哥拿走了,明天輪到你。同時記錄下「老大得到了汽車」(+1),晚上老大回家報道,老爸消掉記錄(-1),汽車空置;3d
週二 ,老二:「老爸,給我鑰匙我要出去浪」,老爸給了他,後來老大又來要鑰匙,老爸說你弟拿走了,明天再來。同時記錄下「老二得到了汽車」(+1),晚上老二回家報道,老爸消掉記錄(-1),汽車空置;code
他倆只能一人出門一人在家嗎?不是的。週三的時候老大老二手拉手一塊兒出去看電影,老大找到老爸,老爸說「能夠」,記錄下「老大得到了汽車」(+1)。老二跟着找老爸,老爸也說「能夠」,同時也作了個記錄「老二也在車裏」(+1)。晚上老大回家報道,老爸消掉一條記錄(-1)。老二跟着報了道,老爸再消一條記錄(-1)。汽車空置。可是若是老二先跑去上廁所忘了跟老爸報備,結果汽車仍然被標記佔用,那麼你們就都用不了了。對象
這個例子中,汽車就是咱們的鎖,老大、老二單獨行動就是兩個獨立的線程,一塊兒行動的話就是一個線程。老爸的記錄就是ReentrantLock對象裏的 State變量,這個變量是volatile線程共享的。當state=0時,即爲資源空置,鎖被線程獲取後 state將從0 -> 1。當線程中嵌套的內部方法又去請求鎖的時候,ReentrantLock會去判斷當前線程是否已經獲取了鎖,若是是,則容許內部方法繼續運行,不過此時 state狀態要加 1,即從 1 -> 2。ReentrantLock的這個機制就是可重入,若是子方法中還有子方法那麼這個值將會從2 -> 3甚至無限大。一個線程重複獲取鎖的時候,須要成對的去釋放鎖,將state從n一直減爲0,釋放資源。少一次釋放,資源就被鎖死;反過來,那麼不可重入就是說當線程已經得到了鎖,那麼子方法是不容許再寫獲取鎖的邏輯了,不然當前線程也被掛起。blog
2、寫個測試代碼資源
/** * ReentrantLock 測試 */ public class ReentrantLockTest2 { public ReentrantLock lock = new ReentrantLock(); /** * 外層方法加鎖 * @throws InterruptedException */ public void test() throws InterruptedException { lock.lock(); try { test2(); // System.out.print("當前鎖得到線程:" + Thread.currentThread().getName() + "\r\n"); } catch (Exception e) { } finally { lock.unlock(); } } /** * 內層方法加鎖 * @throws InterruptedException */ public void test2() throws InterruptedException { lock.lock(); try { test(); System.out.print("當前鎖得到線程:" + Thread.currentThread().getName() + "\r\n"); } catch (Exception e) { } finally { lock.unlock(); } } public static void main(String[] args) throws Exception { ReentrantLockTest2 testObj = new ReentrantLockTest2(); ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < 2; i++) { int finalI = i; executorService.submit(() -> { try { Thread.currentThread().setName("任務"+ finalI); testObj.test(); } catch (InterruptedException e) { e.printStackTrace(); } }); } } }
3、看看源碼get
寫在最後源碼
可重入鎖實際上就這麼簡單,state每重入一次就加1,每釋放一次就減1。原理很簡單,我我的以爲這麼作只是爲了減小鎖機制的使用難度,使用者只用關注方法是否完成了獲取鎖與釋放鎖的邏輯。而不用去管調用鏈上是否已經有人佔據了鎖。