2017-01-03 7 views
3

私は最近いくつかのインタビューを受けました。インタビュアーは保証付きデッドロックの作成を依頼しました。私は次のように書いたしている待機/通知で保証されたデッドロックを書き込む方法

:それはguarantedするされていることを私は確信している場合

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(); 

    } 
} 

それから彼は尋ねました。私は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

これは、1つのスレッドがリソースを保持し、別のリソースを待つサイクルを作成することによって実行できますが、他のスレッドは同じではあるが逆の順序で実行します。デッドロックは、いわゆるライブネス危険(ある

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

t1resourceTwoを保持し、以下resourceOne

待つサンプルコードであるのに対し

スレッドtは、resourceOneを保持し、resourceTwo待ちます他のものは飢え、敏感でない応答、またはライブロック)、ここでは2つの主なタイプが考えられます:

  • ロック発注のデッドロック
  • リソースデッドロックが

、次のように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(); 
     } 
    } 

} 

このデモでは、Sモニターのbのメインスレッドが待機するのに対し、Sモニターのaに作成されたスレッドが待機するので終了したことがありません。その結果、対応するnotify()メソッドは呼び出されません(プログラムが終了します)。

関連する問題