Java-thread-deadlock

提供:Dev Guides
移動先:案内検索

Java-スレッドデッドロック

デッドロックは、2つ以上のスレッドが相互に待機して永久にブロックされる状況を表します。 デッドロックは、複数のスレッドが同じロックを必要とするが、異なるロックを取得するときに発生します。 Javaマルチスレッドプログラムは、 synchronized キーワードによって、指定されたオブジェクトに関連付けられたロックまたはモニターを待機している間、実行中のスレッドがブロックされるため、デッドロック状態になる可能性があります。 これが例です。

public class TestThread {
   public static Object Lock1 = new Object();
   public static Object Lock2 = new Object();

   public static void main(String args[]) {
      ThreadDemo1 T1 = new ThreadDemo1();
      ThreadDemo2 T2 = new ThreadDemo2();
      T1.start();
      T2.start();
   }

   private static class ThreadDemo1 extends Thread {
      public void run() {
         synchronized (Lock1) {
            System.out.println("Thread 1: Holding lock 1...");

            try { Thread.sleep(10); }
            catch (InterruptedException e) {}
            System.out.println("Thread 1: Waiting for lock 2...");

            synchronized (Lock2) {
               System.out.println("Thread 1: Holding lock 1 & 2...");
            }
         }
      }
   }
   private static class ThreadDemo2 extends Thread {
      public void run() {
         synchronized (Lock2) {
            System.out.println("Thread 2: Holding lock 2...");

            try { Thread.sleep(10); }
            catch (InterruptedException e) {}
            System.out.println("Thread 2: Waiting for lock 1...");

            synchronized (Lock1) {
               System.out.println("Thread 2: Holding lock 1 & 2...");
            }
         }
      }
   }
}

上記のプログラムをコンパイルして実行すると、デッドロック状態が見つかり、プログラムによって生成される出力は次のようになります-

出力

Thread 1: Holding lock 1...
Thread 2: Holding lock 2...
Thread 1: Waiting for lock 2...
Thread 2: Waiting for lock 1...

上記のプログラムは、どちらのスレッドも処理を続行できず、互いにロックを解除するのを待機していないため、ハングアップします。そのため、CTRL + Cを押してプログラムから抜けることができます。

デッドロックソリューションの例

同じプログラムのロックと実行の順序を変更して、両方のスレッドがまだお互いを待機しているかどうかを確認しましょう-

public class TestThread {
   public static Object Lock1 = new Object();
   public static Object Lock2 = new Object();

   public static void main(String args[]) {
      ThreadDemo1 T1 = new ThreadDemo1();
      ThreadDemo2 T2 = new ThreadDemo2();
      T1.start();
      T2.start();
   }

   private static class ThreadDemo1 extends Thread {
      public void run() {
         synchronized (Lock1) {
            System.out.println("Thread 1: Holding lock 1...");

            try {
               Thread.sleep(10);
            } catch (InterruptedException e) {}
            System.out.println("Thread 1: Waiting for lock 2...");

            synchronized (Lock2) {
               System.out.println("Thread 1: Holding lock 1 & 2...");
            }
         }
      }
   }
   private static class ThreadDemo2 extends Thread {
      public void run() {
         synchronized (Lock1) {
            System.out.println("Thread 2: Holding lock 1...");

            try {
               Thread.sleep(10);
            } catch (InterruptedException e) {}
            System.out.println("Thread 2: Waiting for lock 2...");

            synchronized (Lock2) {
               System.out.println("Thread 2: Holding lock 1 & 2...");
            }
         }
      }
   }
}

したがって、ロックの順序を変更するだけで、プログラムがデッドロック状態になるのを防ぎ、次の結果で完了します-

出力

Thread 1: Holding lock 1...
Thread 1: Waiting for lock 2...
Thread 1: Holding lock 1 & 2...
Thread 2: Holding lock 1...
Thread 2: Waiting for lock 2...
Thread 2: Holding lock 1 & 2...

上記の例は概念を明確にするためのものですが、それは複雑な概念であり、アプリケーションを開発してからデッドロック状態に対処する前に深く掘り下げる必要があります。