1. 可重入锁的定义
public synchronized void test(){
//business
test1();
}
public synchronized void test1(){
//business
}
在上段代码中,执行test方法需要获取当前对象的监视器锁,而test方法内部又调用了同步方法test1。
如果对象监视器锁是具有可重入性的,那么该线程在调用test1时,可以再次或的对象的监视器锁,从而进入test1方法。
如果对象监视器锁不具有可重入性,那么线程在test方法中调用同步方法test1之前,需要等待当前对象监视器锁的释放,然而,实际上该对象的监视器锁已经被当前线程所持有,不可能再次获得,死锁产生。
综上,锁的可重入性就是一个线程在已经持有锁的情况下,能否再次获取这把锁。
所以,如果有方法的递归调用发生,方法中的锁必须是可重入锁,否则会造成死锁的发生。
BTW,对象监视器锁是可重入锁,所以上面的代码能够正产执行。
2. 可重入锁的使用
同一个可重入锁,被同一线程锁了几次,就需要释放几次。
a) Synchronized修饰的对象监视器锁,在临界区(同步块/同步方法)自动锁定和解锁。
b) ReentrantLock这种显式锁,需要手动释放。
if(reentrantLock.tryLock()){
String currentThreadName = Thread.currentThread().getName();
try {
System.out.println(currentThreadName + " get reentrantLock....");
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println(currentThreadName + " is interrupted....");
} finally{
System.out.println(currentThreadName + " release reentrantLock....");
reentrantLock.unlock();
}
}else{
System.out.println(Thread.currentThread().getName() + " is waiting for lock release....");
this.reentrantLock.lock();
this.run();//do the business
System.out.println(Thread.currentThread().getName() + " release reentrantLock");
this.reentrantLock.unlock();//when using ReentrantLock, recursion lock need recursion unlock
}