Reentrance Lockout的狀況相似於死鎖和nested monitor lockout.Reentrance Lockout在先前的Java中的鎖和Java中的讀寫鎖兩篇文章中都有提到.html
線程在屢次獲取鎖和讀寫鎖實例或是其餘不支持可重入的同步機制時會陷入阻塞即鎖死.可重入意味着線程能夠屢次持有同一把鎖.Javasynchronized
同步塊是可重入的.下面給出可重入的示例代碼:java
public class Reentrant{
public synchronized void outer() {
inner();
}
public synchronized void inner() {
// do something you like
}
}
複製代碼
咱們能夠注意到outer()和inner()方法簽名中都有synchronized
聲明,這在Java中等同於synchronized(this)
同步代碼塊。當多個方法都是以"this"即當前對象做爲監控對象時,那麼一個線程在調用完outer()方法後,天然能夠在outer()方法內部調用inner()方法。一個線程將一個對象做爲監控對象即取得該對象鎖後,它能夠進入其餘使用相同對象做爲對象鎖的同步代碼塊。這種狀況咱們稱之爲可重入。線程能夠反覆進入它所取得監控對象的所有同步代碼塊。post
在以往文章總提到過Lock的實現是不可重入的,以下:性能
public class Lock{
private boolean isLocked = false;
public synchronized void lock() throws InterruptedException{
while(isLocked){
wait();
}
isLocked = true;
}
public synchronized void unlock(){
isLocked = false;
notify();
}
}
複製代碼
若是一個線程在沒有調用unlock()的狀況下,兩次掉調用lock()方法,那麼它將阻塞在第二次lock()方法調用上.這時候reentrance lockout 就會發生了.this
面對這種狀況咱們有兩種選擇:spa
你應該根據實際狀況來選擇.可重入鎖須要提供額外的功能來支持可重入性,所以一般會比不可重入鎖性能要稍差點.還有可重入鎖一般比較難實現,但幸虧Java已經提供了相應的實現了.不管你的代碼實現可重入性如何你都須要謹慎使用可重入鎖.線程
該系列博文爲筆者複習基礎所著譯文或理解後的產物,複習原文來自Jakob Jenkov所著Java Concurrency and Multithreading Tutorial code