2017-09-19 6 views
2

私は現在Java Deadlock Tutorialを使っていますが、プログラムの例では常にデッドロックが発生することを理解しています。 ラムダ式はデッドロックを解決できますか?

public class Deadlock 
    { 
     private static class Friend 
     { 
      private final String name; 
      public Friend(String name) { this.name = name; } 

      public String getName() {return 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"); 

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

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

     } 
    } 

私は適切なラムダ式とスレッドのインスタンス化の1置き換える

new Thread(() -> gaston.bow(alphonse)).start(); デッドロックの問題を解決しているようです。しかし、両方のスレッドのインスタンス化がlambdaに置き換えられると、プログラムは再びデッドロックになります。

これには理由がありますか?

答えて

1

テストでレースがあります。両方のスレッドbowが同時にデッドロックするだけです。

%s: %s has bowed to me!文字列を出力するのに十分な時間は、最初のケースではデッドロックが発生するのに十分ですが、ラムダクラスをインスタンス化する余分な時間が導入されていない場合は発生しません。

ラムダを使用するときは、bowの遅延を導入することにより、テスト・デッドロックを行うことができます。

public synchronized void bow(Friend bower) 
{ 
    System.out.format("%s %s: %s has bowed to me!%n", System.currentTimeMillis(), this.name, bower.getName()); 
    try { 
     Thread.sleep(50); 
    } catch (InterruptedException e) { 
     // ignore 
    } 
    bower.bowBack(this); 
} 

...かによってテストを開始する前に、それをインスタンス化することによって:

public static void main(String[]args) throws InterruptedException { 
    final Friend alphonse = new Friend("alphonse"); 
    final Friend gaston = new Friend("gaston"); 

    // instantiate the runner early 
    Runnable gastonRunner =() -> gaston.bow(alphonse); 

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


    new Thread(gastonRunner).start(); 
} 
関連する問題