Skip to content

Latest commit

 

History

History
45 lines (31 loc) · 2 KB

重入锁死.md

File metadata and controls

45 lines (31 loc) · 2 KB

###重入锁死

重入锁死是一种类似于死锁和嵌套管程失败的情景。

如果一个线程重入获得了一个非重入的锁,读写锁或者一些其他的同步器就会发生重入锁死。重入意味着一个线程已经持有了一个锁可以再次持有它。Java的同步块是可以冲入的。因此,下面这段代码执行将不会出现问题。

public class Reentrant{
    public synchronized outer(){
	    inner();
    }

	public synchronized inner(){
		//do something
	}
}

outerinner方法都被声明为synchronized,这等同于一个synchronized(this)块。如果一个线程在outer()方法里面调用inner()方法将不会出现问题,因为这两个方法都被同步在同一个管程对象"this"上。如果一个线程已经持有了一个管程对象上的锁,它就可以访问同一个管程对象上所有的同步块。这被称作可重入

下面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();
	}
}

如果一个线程两次调用lock()方法而在两次调用之间没有调用unlock(),第二次调用lock()将会阻塞。一个重入锁死就发生了。

要避免重入锁死你有两种选择:

  • 编写代码避免获取已经持有的锁
  • 使用可重入锁

使用哪种方法更适合于你的程序取决于具体的情景。可重入锁的性能常常不如非重入锁,而且更难实现,可重入锁通常没有不可重入锁那么好的表现,而且实现起来复杂,但这些情况在你的项目中也许算不上什么问题。无论你的项目用锁来实现方便还是不用锁方便,可重入特性都需要根据具体问题具体分析。