这个问题的关键在于说明Java没有像我预期的那样工作。
您希望以下代码表现如何?
public class SynchTester {
private static SynchTester synchTester;
public synchronized static SynchTester getSynchTester(){
if(synchTester==null){
synchTester = new SynchTester();
}
return synchTester;
}
private SynchTester() {
SynchTester myTester = getSynchTester();
}
public static void main(String[] args) {
SynchTester tester = SynchTester.getSynchTester();
}
}
我希望它会挂起等待递归完成的死锁,但它会抛出StackOverflow。显然,synchronized不会阻止访问同一个线程。
这是一个错误吗?
答案 0 :(得分:68)
在Java中,同步锁是reentrant。
回想一下,线程无法获取另一个线程拥有的锁。 但线程可以获得已拥有的锁。允许线程多次获取相同的锁可启用重入同步。这描述了一种情况,其中同步代码直接或间接地调用也包含同步代码的方法,并且两组代码使用相同的锁。在没有可重入同步的情况下,同步代码必须采取许多额外的预防措施,以避免线程导致自身阻塞。
来源:见this page
的底部答案 1 :(得分:2)
同步方法需要能够锁定监视器对象。 monitor对象是实例(或静态方法的类)。已经拥有锁的线程不需要再次获取它。所以是的,这可能导致stackoverflow(哈哈尔)。
答案 2 :(得分:2)
当一个线程正在为一个对象执行一个synchronized方法时,所有其他线程都会调用同一个对象的同步方法阻塞(暂停执行),直到第一个线程完成该对象为止。
所以我认为syncronized关键字按预期工作,并且同步递归调用在java中完全合法(并且正常工作)。