2014-11-25 85 views
0

我想從Oracle的網站deadlock瞭解deadlock但不知道爲什麼&兩個自定義線程進入死鎖狀態時。如何在下面的代碼中發生死鎖?

package com.geekthread.java.threads; 

public class DeadLock { 

static class Friend { 
    private final String name; 
    public Friend(String name) { 
     this.name = name; 
    } 
    public String getName() { 
     return this.name; 
    } 
    public synchronized void bow(Friend bower) { 
     System.out.format("%s: %s" 
      + " has bowed to me!%n", 
      this.name, bower.getName()); 

     bower.bowBack(this); 
    } 
    public synchronized void bowBack(Friend bower) { 
     System.out.format("%s: %s" 
      + " has bowed back to me!%n", 
      this.name, bower.getName()); 
    } 


public static void main(String[] args) { 
    final Friend alphonse = 
     new Friend("Alphonse"); 
    final Friend gaston = 
     new Friend("Gaston"); 
     //holds lock for alphonse    
     new Thread(new Runnable() { 
     public void run() { alphonse.bow(gaston); } 
    }).start(); 
    //holds lock for gastone 
    new Thread(new Runnable() { 
     public void run() { gaston.bow(alphonse); } 
    }).start(); 
} 
} 
} 

請糾正我的上述程序的理解: -

1)持有鎖的阿爾方斯·

new Thread(new Runnable() { 
      public void run() { alphonse.bow(gaston); } 
     }).start(); 

2)存放着Gastone的鎖

new Thread(new Runnable() { 
       public void run() { gaston.bow(alphonse); } 
      }).start(); 

我試圖從bowback中刪除同步關鍵字,但不會以死鎖狀態結束,即程序執行完成並且程序在執行後終止。

感謝

回答

0

我definitly不是Java中的專家,但我的猜測是:

由於類朋友是靜態的,類朋友的方法是靜態的。因此這些方法鎖定了類本身而不是類的對象。

這應該提供更多的洞察:8.4.3.6, 'synchronized Methods'

+0

這是錯誤的:「由於Friend類是靜態類,Friend類的方法是靜態的。」類是靜態的,所以我們可以在同一個文件中有多個類。如果'Friend'在它自己的'Friend.java'文件中並且不是靜態的,則會發生死鎖 – dkatzel 2014-11-26 19:50:33

+0

@dkatzel謝謝。沒有意識到java的靜態類概念。 – sbecker 2014-11-27 08:40:33

2

每個對象具有與其相關聯的鎖,也被稱爲隱式鎖或監視器鎖。當​​在你的例子中被用於一個方法時,線程將嘗試取得與該方法對象相關的鎖。所以運行alphonse.bow(gaston);的線程將獲取與alphonse對象關聯的鎖。

幾乎在同一時間,運行gaston.bow(alphonse);的線程將採用與gaston對象關聯的鎖。

所以你有alphonse線程持有alphonse對象的鎖和gaston線程持有gaston對象的鎖。

當alphonse現在試圖執行bower.bowBack(this);時,請注意'bower'是指gaston對象。所以alphonse試圖執行gaston對象的bowBack方法。由於bowBack方法是同步的,因此alphonse需要獲取gaston對象鎖繼續。但當然gaston線程已經有了gaston對象鎖!

所以alphonse試圖執行gaston的bowback方法,但不能,因爲它無法獲得gaston對象鎖定。

與此同時,gaston也有同樣的問題。他需要調用alphonse的bowBack方法,但alphonse線程已經有alphonse對象鎖。

所以每個線程都有一個鎖,並試圖獲得另一個線程已經擁有的鎖並且都不能繼續 - 一個典型的死鎖場景..

編輯:去除bowBack「同步」防止僵局,因爲你發現,因爲現在有什麼阻礙阿方線程調用加斯頓的bowBack方法 - 阿爾方不再需要獲得加斯頓對象鎖定該加斯頓持有。相同的邏輯適用於與gaston相反的人,他也可以繼續。