同步方法以递归方式调用自身。这坏了吗?

时间:2012-11-02 15:00:06

标签: java recursion synchronized

这个问题的关键在于说明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不会阻止访问同一个线程。

这是一个错误吗?

3 个答案:

答案 0 :(得分:68)

在Java中,同步锁是reentrant

  

回想一下,线程无法获取另一个线程拥有的锁。 但线程可以获得已拥有的锁。允许线程多次获取相同的锁可启用重入同步。这描述了一种情况,其中同步代码直接或间接地调用也包含同步代码的方法,并且两组代码使用相同的锁。在没有可重入同步的情况下,同步代码必须采取许多额外的预防措施,以避免线程导致自身阻塞。

来源:见this page

的底部

答案 1 :(得分:2)

同步方法需要能够锁定监视器对象。 monitor对象是实例(或静态方法的类)。已经拥有锁的线程不需要再次获取它。所以是的,这可能导致stackoverflow(哈哈尔)。

答案 2 :(得分:2)

来自java tutorials

  

当一个线程正在为一个对象执行一个synchronized方法时,所有其他线程都会调用同一个对象的同步方法阻塞(暂停执行),直到第一个线程完成该对象为止。

所以我认为syncronized关键字按预期工作,并且同步递归调用在java中完全合法(并且正常工作)。