【问题标题】:Calling a synchronized method from of a synchronized method, both of the same object [duplicate]从同步方法中调用同步方法,两者都是同一个对象[重复]
【发布时间】:2013-03-04 14:34:41
【问题描述】:

为什么下面的代码不会导致死锁?我的意思是在我调用 getNumber(.) 之后,Test 类的对象应该被锁定,所以我不应该能够访问 getNumber2(.)。

class Test() {
    synchronized int getNumber(int i){
        return getNumber2(i);
    }

    synchronized int getNumber2(int i) {
        return i;
    }

    public static void main(String[] args) {
        System.out.println((new Test()).getNumber(100));
    }
}

输出:

100

【问题讨论】:

  • 与此类似的帖子:stackoverflow.com/questions/5798637/…
  • 是的,问题是一样的,但上下文却完全不同。这个问题一直在问死锁,另一个是关于线程安全的。

标签: java synchronized


【解决方案1】:

这是因为锁是可重入的,也就是说它可以被同一个线程多次获取。

来自Java tutorial

重入同步

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

JLS的相关部分是§17.1. Synchronization:

Java 编程语言为线程之间的通信提供了多种机制。这些方法中最基本的是同步,它是使用监视器实现的。 Java 中的每个对象都与一个监视器相关联,线程可以锁定或解锁监视器。一次只有一个线程可以锁定监视器。任何其他试图锁定该监视器的线程都会被阻塞,直到它们能够获得对该监视器的锁定。 一个线程可能会多次锁定一个特定的监视器;每次解锁都会反转一次锁定操作的效果。

【讨论】:

    【解决方案2】:

    它不会导致死锁,因为当一个线程进入一个同步方法时,它所做的是检查它在this上是否有锁,如果没有,它会一直等到它可以有锁并得到它。

    在你的情况下,当线程进入第二个同步方法时,它已经锁定了this对象,所以它可以进入方法而不会阻塞。

    【讨论】:

      猜你喜欢
      • 2011-08-13
      • 2012-03-20
      • 2023-04-07
      • 2011-11-28
      • 2017-09-23
      • 1970-01-01
      • 2015-02-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多