2013-03-04 133 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對象,所以它可以進入方法沒有阻塞。