@[toc]
鎖的分類

什麼是可重入鎖
可重入鎖又名遞歸鎖,是指在同一個線程在外層方法擷取鎖的時候,再進入該線程的内層方法會自動擷取鎖(前提鎖對象得是同一個對象或者class),不會因為之前已經擷取過還沒釋放而阻塞。Java中ReentrantLock和synchronized都是可重入鎖,可重入鎖的一個優點是可一定程度避免死鎖。
- ReentrantLock和synchronized都是重入鎖,
- 可重入鎖的好處:【1.避免死鎖】【2.提升封裝性】
案例實作
- 電影院預定預定電影院座位
預定座位就是個很好的lock鎖場景,預定座位,其實這個背後就是上鎖了
首先ReentrantLock和NonReentrantLock都繼承父類AQS,其父類AQS中維護了一個同步狀态status來計數重入次數,status初始值為0。
當線程嘗試擷取鎖時,可重入鎖先嘗試擷取并更新status值,如果status == 0表示沒有其他線程在執行同步代碼,則把status置為1,目前線程開始執行。如果status != 0,則判斷目前線程是否是擷取到這個鎖的線程,如果是的話執行status+1,且目前線程可以再次擷取鎖。而非可重入鎖是直接去擷取并嘗試更新目前status的值,如果status != 0的話會導緻其擷取鎖失敗,目前線程阻塞。
釋放鎖時,可重入鎖同樣先擷取目前status的值,在目前線程是持有鎖的線程的前提下。如果status-1 == 0,則表示目前線程所有重複擷取鎖的操作都已經執行完畢,然後該線程才會真正釋放鎖。而非可重入鎖則是在确定目前線程是持有鎖的線程之後,直接将status置為0,将鎖釋放。
測試lock 鎖的可重入性
我們使用 lock.getHoldCount() 列印下擷取鎖的次數
多次擷取鎖,與釋放鎖
會發現鎖不用等待,下一次依然可以擷取到鎖,這就是鎖的可重入鎖性
不可重入鎖
不可重入鎖,與可重入鎖相反,不可遞歸調用,遞歸調用就會發生死鎖。