synchronized声明的内部锁是可重入的,并且可重入是基于每一个线程获得一次锁,而不是每一次调用获得一次锁。
暂时没听懂没关系,先看看可重入是怎么实现的。可重入是通过请求计数值和拥有者线程实现的。当计数值为0时,线程进入synchronized块会获得锁,计数值加一,设置该线程为拥有者线程。但其他线程尝试加锁时会阻塞。
可重入意味着该拥有线程未释放锁时可再次进入同步块(synchronized)并获得锁,计数值加一。
下面看一个例子:
public class Widget {
public synchronized void doSomething() {
...
}
}
public class LoggingWidget extends Widget {
public synchronized void doSomething() {
System.out.println(toString() + ": calling doSomething");
super.doSomething();
}
}
当LoggingWidget创建一个对象A,A调用方法doSomething()时,该线程获得A的锁,A.doSomething()中又调用父类的doSomething(),该线程又尝试获得A的锁来进入父类的方法(注意,调用父类方法时获得子类的锁),由于内部锁是可重入的,因此该线程再次获得锁,并进入同步方法。
如果内部锁不是可重入的,那么就进入不了父类的方法,造成死锁。
参考:
https://stackoverflow.com/questions/21399270/extended-classes-synchronized-methods-locking