重入鎖死與死鎖和嵌套管程鎖死很是類似。鎖和讀寫鎖兩篇文章中都有涉及到重入鎖死的問題。html
當一個線程從新獲取鎖,讀寫鎖或其餘不可重入的同步器時,就可能發生重入鎖死。可重入的意思是線程能夠重複得到它已經持有的鎖。Java的synchronized塊是可重入的。所以下面的代碼是沒問題的:java
(譯者注:這裏提到的鎖都是指的不可重入的鎖實現,並非Java類庫中的Lock與ReadWriteLock類)segmentfault
public class Reentrant{ public synchronized outer(){ inner(); } public synchronized inner(){ //do something } }
注意outer()和inner()都聲明爲synchronized,這在Java中這至關於synchronized(this)塊(譯者注:這裏兩個方法是實例方法,synchronized的實例方法至關於在this上加鎖,若是是static方法,則否則,更多閱讀:哪一個對象纔是鎖?)。若是某個線程調用了outer(),outer()中的inner()調用是沒問題的,由於兩個方法都是在同一個管程對象(即this)上同步的。若是一個線程持有某個管程對象上的鎖,那麼它就有權訪問全部在該管程對象上同步的塊。這就叫可重入。若線程已經持有鎖,那麼它就能夠重複訪問全部使用該鎖的代碼塊。this
下面這個鎖的實現是不可重入的:spa
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(); } }
若是一個線程在兩次調用lock()間沒有調用unlock()方法,那麼第二次調用lock()就會被阻塞,這就出現了重入鎖死。線程
避免重入鎖死有兩個選擇:code
至於哪一個選擇最適合你的項目,得視具體狀況而定。可重入鎖一般沒有不可重入鎖那麼好的表現,並且實現起來複雜,但這些狀況在你的項目中也許算不上什麼問題。不管你的項目用鎖來實現方便仍是不用鎖方便,可重入特性都須要根據具體問題具體分析。htm
原文 Reentrance Lockout
做者 Jakob Jenkov
譯者 劉曉日
校對 丁一
via ifeve對象