2013-03-04 100 views
5

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

类似的文章到这:http://stackoverflow.com/questions/5798637/is-it-safe-to-call-a-synchronized-method-from-another-synchronized-method – Walls 2013-03-04 14:37:45

+0

是的问题是相同的,但上下文有很大不同。在这个问题上,它一直在问关于死锁,另一个关于线程安全。 – Lovera 2017-09-25 14:27:42

回答

19

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

Java tutorial

折返同步

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

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

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

4

它不会导致死锁,因为当一个线程进入一个同步的方法,它的作用是检查它对this锁,那么如果它不,它等待,直到它可以有锁定并获取它。

当你的案例中的线程进入第二个同步方法时,它已经锁定了this对象,所以它可以进入方法没有阻塞。