31

这个问题的重点是说明 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。显然同步不会阻止对同一线程的访问。

这是一个错误吗?

4

3 回答 3

78

在 Java 中,同步锁是可重入的。

回想一下,一个线程不能获得另一个线程拥有的锁。但是线程可以获取它已经拥有的锁。允许一个线程多次获取同一个锁可以实现重入同步。这描述了一种情况,同步代码直接或间接调用一个也包含同步代码的方法,并且两组代码都使用相同的锁。如果没有可重入同步,同步代码将不得不采取许多额外的预防措施来避免线程导致自身阻塞。

来源:见本页底部

于 2012-11-02T15:09:27.883 回答
3

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

于 2012-11-02T15:07:58.503 回答
3

来自java教程

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

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

于 2012-11-02T15:09:20.973 回答