Javaの例 - デッドロックとソリューション
デッドロックが状況です:複数のスレッドがブロックされ、1またはそれらのすべてが解放されるリソースを待っています。 スレッドが無期限にブロックされているので、そのようにプログラムが正常に終了することができません。
必要な4つの条件のjavaデッドロック:
- リソースは、スレッド(所持)のとき1、排他的な使用であること、他のスレッドを使用することはできません
- 2は、リソースの要求者をつかむことができないリソース、リソースの所有者の手からリソースをつかむように強制することはできません、リソースが唯一のイニシアチブの乗員によって解除することができます。
- 3、リクエスト、およびときに、リソースの要求者は元のリソースの所有権を維持するために追加のリソースを要求しながらことを維持します。
- 図4は、サイクルを待って、すなわち、キューがあります:P1、P2は、リソース、P2とP3のリソースの所有、資源のP1 P3のシェアを占めています。 したがって待ちループを形成します。
これらの4つの条件が満たされたとき、デッドロック。 これらの条件のいずれかを破るために、デッドロックの場合場合はもちろん、あなたがデッドロックが消えることができます。 農産物をデッドロックのJavaどのようなシミュレートするために、次のコードを使用します。
デッドロックの問題を解決するには、次のとおりです。同期されているものは、1はロックの明示的なロックを使用することです。
ロックの使用、および複数のオブジェクトをロックすると同時に、画面が不適切な場合は、次のように、デッドロック状態があります:
/* author by w3cschool.cc LockTest.java */ import java.util.Date; public class LockTest { public static String obj1 = "obj1"; public static String obj2 = "obj2"; public static void main(String[] args) { LockA la = new LockA(); new Thread(la).start(); LockB lb = new LockB(); new Thread(lb).start(); } } class LockA implements Runnable{ public void run() { try { System.out.println(new Date().toString() + " LockA 开始执行"); while(true){ synchronized (LockTest.obj1) { System.out.println(new Date().toString() + " LockA 锁住 obj1"); Thread.sleep(3000); // 此处等待是给B能锁住机会 synchronized (LockTest.obj2) { System.out.println(new Date().toString() + " LockA 锁住 obj2"); Thread.sleep(60 * 1000); // 为测试,占用了就不放 } } } } catch (Exception e) { e.printStackTrace(); } } } class LockB implements Runnable{ public void run() { try { System.out.println(new Date().toString() + " LockB 开始执行"); while(true){ synchronized (LockTest.obj2) { System.out.println(new Date().toString() + " LockB 锁住 obj2"); Thread.sleep(3000); // 此处等待是给A能锁住机会 synchronized (LockTest.obj1) { System.out.println(new Date().toString() + " LockB 锁住 obj1"); Thread.sleep(60 * 1000); // 为测试,占用了就不放 } } } } catch (Exception e) { e.printStackTrace(); } } }
上記のコードは出力され実行されます。
Tue May 05 10:51:06 CST 2015 LockB 开始执行 Tue May 05 10:51:06 CST 2015 LockA 开始执行 Tue May 05 10:51:06 CST 2015 LockB 锁住 obj2 Tue May 05 10:51:06 CST 2015 LockA 锁住 obj1
このデッドロックで。
この問題を解決するために、我々は我々が制御するためにセマフォを使用して、ロックを表示するために使用しないでください。
セマフォは、リソースにアクセスすることができますどのように多くのスレッドを制御することができ、我々はここで指定した複数のスレッドにアクセスすることができ、あなたは同じようなロックを行います。 セマフォは、我々がタイムアウトに応じてすることができます得るためにタイムアウトを指定し、余分な治療を行うことができます。
取得できない場合は、一般的には試行回数を試行を繰り返し、または指定することで、あなたはすぐに終了することができます。
次のコードを見てください:
/* author by w3cschool.cc UnLockTest.java */ import java.util.Date; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; public class UnLockTest { public static String obj1 = "obj1"; public static final Semaphore a1 = new Semaphore(1); public static String obj2 = "obj2"; public static final Semaphore a2 = new Semaphore(1); public static void main(String[] args) { LockAa la = new LockAa(); new Thread(la).start(); LockBb lb = new LockBb(); new Thread(lb).start(); } } class LockAa implements Runnable { public void run() { try { System.out.println(new Date().toString() + " LockA 开始执行"); while (true) { if (UnLockTest.a1.tryAcquire(1, TimeUnit.SECONDS)) { System.out.println(new Date().toString() + " LockA 锁住 obj1"); if (UnLockTest.a2.tryAcquire(1, TimeUnit.SECONDS)) { System.out.println(new Date().toString() + " LockA 锁住 obj2"); Thread.sleep(60 * 1000); // do something }else{ System.out.println(new Date().toString() + "LockA 锁 obj2 失败"); } }else{ System.out.println(new Date().toString() + "LockA 锁 obj1 失败"); } UnLockTest.a1.release(); // 释放 UnLockTest.a2.release(); Thread.sleep(1000); // 马上进行尝试,现实情况下do something是不确定的 } } catch (Exception e) { e.printStackTrace(); } } } class LockBb implements Runnable { public void run() { try { System.out.println(new Date().toString() + " LockB 开始执行"); while (true) { if (UnLockTest.a2.tryAcquire(1, TimeUnit.SECONDS)) { System.out.println(new Date().toString() + " LockB 锁住 obj2"); if (UnLockTest.a1.tryAcquire(1, TimeUnit.SECONDS)) { System.out.println(new Date().toString() + " LockB 锁住 obj1"); Thread.sleep(60 * 1000); // do something }else{ System.out.println(new Date().toString() + "LockB 锁 obj1 失败"); } }else{ System.out.println(new Date().toString() + "LockB 锁 obj2 失败"); } UnLockTest.a1.release(); // 释放 UnLockTest.a2.release(); Thread.sleep(10 * 1000); // 这里只是为了演示,所以tryAcquire只用1秒,而且B要给A让出能执行的时间,否则两个永远是死锁 } } catch (Exception e) { e.printStackTrace(); } } }
上記コードの出力構造の例:
Tue May 05 10:59:13 CST 2015 LockA 开始执行 Tue May 05 10:59:13 CST 2015 LockB 开始执行 Tue May 05 10:59:13 CST 2015 LockB 锁住 obj2 Tue May 05 10:59:13 CST 2015 LockA 锁住 obj1 Tue May 05 10:59:14 CST 2015LockB 锁 obj1 失败 Tue May 05 10:59:14 CST 2015LockA 锁 obj2 失败 Tue May 05 10:59:15 CST 2015 LockA 锁住 obj1 Tue May 05 10:59:15 CST 2015 LockA 锁住 obj2