2013-10-20 49 views
0

我想實現死鎖條件,但不知何故我無法讓它工作。線程Thread1和Thread2都進入運行功能,但只有其中一個進入Sub/Sum取決於誰先進入運行。例如:如果Thread2輸入先運行,它將調用sub(),而Thread1從不調用sum()。我還增加了睡眠時間,以便在調用sum()之前讓Thread2休眠,並且Thread1有足夠的時間輸入Sum(),但Thread1永遠不會進入。實現死鎖條件

public class ExploringThreads { 
     public static void main(String[] args) { 
      // TODO Auto-generated method stub 
      threadexample a1 = new threadexample(); 
      Thread t1 = new Thread(a1, "Thread1"); 
      Thread t2 = new Thread(a1,"Thread2"); 
      t1.start(); 
      t2.start(); 
     } 
    } 
    class threadexample implements Runnable{ 
     public int a = 10; 
     public void run(){ 
      if(Thread.currentThread().getName().equals("Thread1")) 
       sum(); 
      else if(Thread.currentThread().getName().equals("Thread2")) 
       sub(); 
     } 

     public synchronized void sum() 
     { 
      try { 
       Thread.sleep(2000); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      System.out.println(Thread.currentThread().getName()+"In Sum"); 
      sub(); 
     } 

     public synchronized void sub() 
     { 
      try { 
       Thread.sleep(2000); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      System.out.println(Thread.currentThread().getName()+"In Sub"); 
      sum(); 
     } 
    } 

回答

1

這不是你如何得到一個死鎖。其實這段代碼看起來很安全:-)一次只有一個線程輸入sum/sub,因爲你使用synchronized來同步「this」。只有一個「this」,所以兩個線程都試圖獲得相同的鎖。

例如,當Thread1有一個鎖時,Thread2有第二個鎖,然後Thread1想要獲得Thread2的鎖而仍然保持它的鎖並且Thread2想要在獲取Thread1的鎖的同時仍然保持它的鎖,就會發生死鎖。

你可以做的是:

一)增加2個對象爲按照慣例在 「threadexample」 級鎖(順便說一句類應以大寫開頭):

private final Object sumLock = new Object(); 
private final Object subLock = new Object(); 

B)去掉「同步「關鍵字在sum/sub方法中,而是在每個方法中使用synchronized(){}塊。總和將被同步(sumLock){/ * sum的正文在這裏/}和sub將被同步(subLock){/ sub的身體去這裏* /}。

在這種情況下,Thread1會進入sum(),獲取sumLock並等待。 Thread2會進入sub(),獲取subLock()並等待。 Thread1會喚醒,進入sub()並嘗試獲取subLock,但它由Thread2保存,所以它等待,直到Thread2釋放它。在那段時間,Thread2喚醒,進入sum()並嘗試獲取由Thread1持有的sumLock,所以Thread2等待Thread1釋放它。

兩個線程都不會前進,因爲每個線程都在等待另一個線程 - 您有一個死鎖。

@編輯:是的,你只有1個「threadexample」實例,Thread1和Thread2都在爭奪鎖,但是當其中一個獲得鎖時,它將在執行sum/sub或sub/sum後釋放它。比如讓我們說Thread1是第一個,並開始執行sum()。它有鎖。在這種情況下,Thread2不會進入sub(),因爲它受到與Thread1相同的鎖的保護。 Thread1將執行sum(),然後sub()然後釋放鎖 - > Thread2將進入sub()等。

+0

抱歉,我不明白。這可能是因爲我是線程新手。根據我的理解,我只做了一個類threadexample的對象。並且Thread1和Thread2競爭對sum()和sub()的鎖定。 – Bhaskar

1

如果你真的想創建一個人爲的死鎖,試試這個:
Thread1Thread2是兩個想要訪問同一個文件的線程。

  1. Thread1開始,要求鎖定File1.docx並睡2分鐘。
  2. Thread2開始,並在File2.docx上獨佔鎖定,現在想要訪問File1.docx
  3. Thread1醒來,現在想訪問File2.docx這是由Thread2

現在舉行,這是一個循環等待條件

簡單嗎? =)

+1

你的例子不正確。只要'Thread'沒有釋放它的鎖,'Thread2'就被阻塞*,但這不是死鎖。當兩個(或更多)線程永久阻塞時會發生死鎖情況,因爲每個線程都被阻塞,等待獲得另一個線程的獨佔資源。 – Miguel

+0

@Miguel現在正確嗎? =)謝謝指出! –

+0

是的,現在這是一個僵局的正確例子。 – Miguel

0

這是'Deadlock in Action'的一個工作示例。基本上你需要做的(以及如何,通常發生在現實世界)是該對象被鎖定在相反的順序:在一個線程中第一,B第二和b第一,第二在另一:

package stackoverflow; 

public class Deadlock { 

    final static String a = new String("A"); 
    final static String b = new String("B"); 

    public static void main(String[] args) { 

     final Thread abLock = new Thread() { 
      @Override 
      public void run() { 
       lock(a, b); 
      } 
     }; 

     final Thread baLock = new Thread() { 
      @Override 
      public void run() { 
       lock(b, a); 
      } 
     }; 

     abLock.start(); 
     baLock.start(); 

    } 

    static void lock(String first, String second) { 
     synchronized (first) { 
      System.out.println(first); 
      sleep(); 
      synchronized (second) { 
       System.out.println(second); 
      } 
     } 
    } 

    static void sleep() { 
     try { 
      Thread.sleep(500); 
     } catch (InterruptedException e) { 
      throw new RuntimeException(e); 
     } 
    } 

}