2017-01-03 43 views
3

最近我訪問了一些面試。採訪者要求我寫保證的死鎖。如何通過wait/notify寫保證死鎖

我已經寫了以下內容:

public class DeadLockThreadSleep { 
    private static class MyThread implements Runnable { 
     private Object o1; 
     private Object o2; 

     @Override 
     public void run() { 
      try { 
       test(o1, o2); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 

     public MyThread(Object o1, Object o2) { 
      this.o1 = o1; 
      this.o2 = o2; 
     } 

     public void test(Object o1, Object o2) throws InterruptedException { 
      synchronized (o1) { 
       System.out.println("1.acquired: " + o1); 
       Thread.sleep(1000); 
       synchronized (o2) { 
        System.out.println("2.acquired: " + o2); 

       } 
      } 
     } 
    } 

    public static void main(String[] args) { 
     Object o1 = new Object(); 
     Object o2 = new Object(); 
     new Thread(new MyThread(o1, o2)).start(); 
     new Thread(new MyThread(o2, o1)).start(); 

    } 
} 

然後他問,如果我確信它是guaranted。我重新記住了Thread.sleep沒有任何保證。

然後我寫了這個代碼:

public static void main(String[] args) { 
     final Thread mainThread = Thread.currentThread(); 
     Thread thread = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        mainThread.join(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
     thread.start(); 
     try { 
      thread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

這個答案被接受。

他還要求通過等待/通知寫模擬。我想了很多,我無法想象如何寫這個。

可能嗎?

+0

http://stackoverflow.com/questions/19908498/deadlocks-using-wait-and-notify – assylias

+0

@assylias我讀過這個話題。在最高票選答案不是答案 – gstackoverflow

回答

1

這可以通過創建一個循環來完成,其中一個線程保存一個資源並等待另一個資源,而另一個線程執行相同的操作,但順序相反。

螺紋t保持resourceOne並等待resourceTwo,而t1持有resourceTwo並等待resourceOne

下面是一個示例代碼:

public class WaitNotifyLock { 

     boolean isONHold = false; 
     public synchronized void hold(){ 
      while(isONHold){ 
       try { 
        wait(); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
     isONHold = true; 
     System.out.println(Thread.currentThread().getId() + " : Holded"); 
    } 

    public synchronized void unHold(){ 
     while(!isONHold){ 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
     System.out.println(Thread.currentThread().getId() + " : Produced"); 
     isONHold = false; 
     notify(); 
    } 

    public static void main(String[] args) { 
     WaitNotifyLock resourceOne = new WaitNotifyLock(); 
     WaitNotifyLock resourceTwo = new WaitNotifyLock(); 
     Thread t = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       // TODO Auto-generated method stub 
       resourceOne.hold(); 
       try { 
        Thread.sleep(2); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       resourceTwo.hold(); 
       resourceOne.unHold(); 
       resourceTwo.unHold(); 
      } 
     }); 

     Thread t1 = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       resourceTwo.hold(); 
       try { 
        Thread.sleep(2); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
         e.printStackTrace(); 
       } 
       resourceOne.hold(); 
       resourceTwo.unHold(); 
       resourceOne.unHold(); 
       } 
      }); 

      t.start(); 
      t1.start(); 
     } 

    } 
1

死鎖是一個所謂的活躍危險(其他人是飢餓,反應遲鈍或活鎖),其中可以考慮兩種主要類型:

  • 鎖排序死鎖
  • 資源死鎖

然而,Java documentation簡化了這個如下:

死鎖描述了兩個或多個線程永遠阻塞的情況下,等待對於彼此。

因此,恕我直言,你可以簡單地執行這個死鎖:

public class DeadlockDemo { 

    public static void main(String[] args) { 
     Object a = new Object(); 
     Object b = new Object(); 

     new Thread(() -> waitLeftNotifyRight(a, b)).start(); 
     waitLeftNotifyRight(b, a); 
    } 

    public static void waitLeftNotifyRight(Object left, Object right) { 
     synchronized (left) { 
      try { 
       System.out.println("Wait"); 
       left.wait(); 
      } catch (InterruptedException e) { /* NOP */ } 
     } 
     synchronized (right) { 
      System.out.println("Notify"); 
      right.notify(); 
     } 
    } 

} 

這個演示永遠不會終止,因爲a在創建線程等待的顯示器,而b在主線程等待的顯示器。因此,不會調用相應的notify()方法(這會終止程序)。