从同步方法调用同步方法,两者都是同一个对象

时间:2013-03-04 14:34:41

标签: java synchronized

为什么下面的代码不会导致死锁?我的意思是在我调用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

2 个答案:

答案 0 :(得分:19)

这是因为锁是可重入的,这意味着它可以被同一个线程多次获取。

来自Java tutorial

  

可重入同步

     

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

JLS的相关部分是§17.1. Synchronization

  

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

答案 1 :(得分:4)

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

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