可重入鎖,指的是以線程為單位,當一個線程獲取對象鎖之后,這個線程可以再次獲取本對象上的鎖,而其他的線程是不可以的。
synchronized 和 ReentrantLock 都是可重入鎖。
可重入鎖的意義之一在於防止死鎖。
實現原理實現是通過為每個鎖關聯一個請求計數器和一個占有它的線程。當計數為0時,認為鎖是未被占有的;線程請求一個未被占有的鎖時,JVM將記錄鎖的占有者,並且將請求計數器置為1 。
如果同一個線程再次請求這個鎖,計數器將遞增;
每次占用線程退出同步塊,計數器值將遞減。直到計數器為0,鎖被釋放。
關於父類和子類的鎖的重入:子類覆寫了父類的synchonized方法,然后調用父類中的方法,此時如果沒有可重入的鎖,那么這段代碼將產生死鎖(很好理解吧)。
例子:
比如說A類中有個方法public synchronized methodA1(){
methodA2();
}
而且public synchronized methodA2(){
//具體操作
}
也是A類中的同步方法,當當前線程調用A類的對象methodA1同步方法,如果其他線程沒有獲取A類的對象鎖,那么當前線程就獲得當前A類對象的鎖,然后執行methodA1同步方法,方法體中調用methodA2同步方法,當前線程能夠再次獲取A類對象的鎖,而其他線程是不可以的,這就是可重入鎖。
一個有趣的例子:
一個線程執行synchronized同步代碼時,再次重入該鎖過程中,如果拋出異常,是否會釋放鎖:https://www.cnblogs.com/theRhyme/p/10078402.html
JAVA線程狀態、線程START方法源碼、JAVA線程池、如何停止一個線程
MySQL實現的分布式鎖
https://www.cnblogs.com/theRhyme/p/9776951.html
對於MySQL的分布式鎖我們可以創建一個鎖表:
這個鎖的數據結構主要是唯一鍵resource_name(機器ip+線程名)和count(統計可重入鎖)。
這里的resource_name相當於占有該鎖的線程,count相當於計數器。
參考來源: