Java のデッドロックはマルチスレッドの一部です。デッドロックは、スレッドが別のスレッドによって取得されたオブジェクト ロックを待機しており、2 番目のスレッドが最初のスレッドによって取得されたオブジェクト ロックを待機している状況で発生する可能性があります。両方のスレッドがお互いにロックを解放するのを待っているため、この状態はデッドロックと呼ばれます。
Java でのデッドロックの例
TestDeadlockExample1.java
public class TestDeadlockExample1 { public static void main(String[] args) { final String resource1 = 'ratan jaiswal'; final String resource2 = 'vimal jaiswal'; // t1 tries to lock resource1 then resource2 Thread t1 = new Thread() { public void run() { synchronized (resource1) { System.out.println('Thread 1: locked resource 1'); try { Thread.sleep(100);} catch (Exception e) {} synchronized (resource2) { System.out.println('Thread 1: locked resource 2'); } } } }; // t2 tries to lock resource2 then resource1 Thread t2 = new Thread() { public void run() { synchronized (resource2) { System.out.println('Thread 2: locked resource 2'); try { Thread.sleep(100);} catch (Exception e) {} synchronized (resource1) { System.out.println('Thread 2: locked resource 1'); } } } }; t1.start(); t2.start(); } }
出力:
Thread 1: locked resource 1 Thread 2: locked resource 2
より複雑なデッドロック
デッドロックには 3 つ以上のスレッドが含まれる場合もあります。その理由は、デッドロックを検出するのが難しい場合があるためです。次に、4 つのスレッドがデッドロックした例を示します。
スレッド 1 は A をロックし、B を待機します
スレッド 2 は B をロックし、C を待ちます
スレッド 3 は C をロックし、D を待ちます
スレッド 4 は D をロックし、A を待ちます
スレッド 1 はスレッド 2 を待機し、スレッド 2 はスレッド 3 を待機し、スレッド 3 はスレッド 4 を待機し、スレッド 4 はスレッド 1 を待機します。
デッドロックを回避するにはどうすればよいでしょうか?
問題の解決策はその根本にあります。デッドロックでは、リソース A と B にアクセスするパターンが主な問題になります。この問題を解決するには、コードが共有リソースにアクセスしているステートメントを単純に並べ替える必要があります。
デッドロック解決済み.java
public class DeadlockSolved { public static void main(String ar[]) { DeadlockSolved test = new DeadlockSolved(); final resource1 a = test.new resource1(); final resource2 b = test.new resource2(); // Thread-1 Runnable b1 = new Runnable() { public void run() { synchronized (b) { try { /* Adding delay so that both threads can start trying to lock resources */ Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // Thread-1 have resource1 but need resource2 also synchronized (a) { System.out.println('In block 1'); } } } }; // Thread-2 Runnable b2 = new Runnable() { public void run() { synchronized (b) { // Thread-2 have resource2 but need resource1 also synchronized (a) { System.out.println('In block 2'); } } } }; new Thread(b1).start(); new Thread(b2).start(); } // resource1 private class resource1 { private int i = 10; public int getI() { return i; } public void setI(int i) { this.i = i; } } // resource2 private class resource2 { private int i = 20; public int getI() { return i; } public void setI(int i) { this.i = i; } } }
出力:
In block 1 In block 2
上記のコードでは、DeadlockSolved クラスがデッドロックのような状況を解決します。これは、デッドロックを回避し、デッドロックが発生した場合には解決するのに役立ちます。
Java でデッドロックを回避するには?
デッドロックを完全に解決することはできません。ただし、以下に示す基本的なルールに従うことで、それらを回避できます。