重入锁死与死锁和嵌套管程锁死很是类似。锁和读写锁两篇文章中都有涉及到重入锁死的问题。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对象