スレッドのデッドロックおよびデッドロックの発生を回避する方法についての概要
デッドロックコンセプト:複数のスレッドが同時にブロックされている場合、それらの間で互いにリソースの解放を待つと、デッドロックが発生します.
デッドロックを生成するには、次の4つの条件が必要です.反発条件:リソースの任意の時点で1つのスレッドのみが占有されます. 要求と保持条件:1つのプロセスが要求リソースによってブロックされた場合、取得したリソースは保持されません. 条件を剥奪しない:スレッドが取得したリソースは、使用が完了する前に他のスレッドに強制的に剥奪されず、自分が使用が完了した後にのみリソースを解放する. サイクル待機条件:いくつかのプロセスの間にヘッドとテールが接続されたサイクル待機リソース関係が形成される.スレッドのデッドロックを回避するにはどうすればいいですか? 反発条件を破壊します:この条件は破壊できません.私たちは索を使ってもともと反発させたいからです. は、要求と保持条件を破壊します.一度にリソースを申請します. 破壊不剥奪条件:占有部門のリソーススレッドはさらに他のリソースを申請し、申請ができない場合は、その占有リソースを自発的に解放することができる. サイクル待ち条件の破壊:リソースを順番に申請することによって予防される.ある順序でリソースを申請し、リソースを解放すると逆順序で解放されます.ループ待ち条件を破壊します.
コードを変更してもデッドロックは発生しません.
理由:スレッド1はまずresource 1のモニタロックを取得し,このときスレッド2は取得できない.そしてスレッド1はresource 2のモニタロックを取得し、取得することができる.そしてスレッド1はresource 1,resource 2のモニタロックの占有を解放し,スレッド2が取得すれば実行できる.これにより、デッドロックが回避されるため、サイクル待機条件が破壊される.
public class ThreadDemo_01 {
private static Object resource1=new Object(); // 1
private static Object resource2=new Object(); // 2
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
synchronized (resource1){
System.out.println(Thread.currentThread()+"get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"waiting get resource2");
synchronized (resource2){
System.out.println(Thread.currentThread()+"get resource2");
}
}
}
}," 1").start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (resource2){
System.out.println(Thread.currentThread()+"get resource2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"waiting get resource1");
synchronized (resource1){
System.out.println(Thread.currentThread()+"get resource1");
}
}
}
}," 2").start();
}
}
デッドロックを生成するには、次の4つの条件が必要です.
コードを変更してもデッドロックは発生しません.
public class StringDemo_01 {
private static Object resource1=new Object();
private static Object resource2=new Object();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
synchronized (resource1){
System.out.println(Thread.currentThread()+"get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"waiting get resource2");
synchronized (resource2){
System.out.println(Thread.currentThread()+"get resource2");
}
}
}
}," 1").start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (resource1){
System.out.println(Thread.currentThread()+"get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"waiting get resource2");
synchronized (resource2){
System.out.println(Thread.currentThread()+"get resource2");
}
}
}
}," 2").start();
}
}
理由:スレッド1はまずresource 1のモニタロックを取得し,このときスレッド2は取得できない.そしてスレッド1はresource 2のモニタロックを取得し、取得することができる.そしてスレッド1はresource 1,resource 2のモニタロックの占有を解放し,スレッド2が取得すれば実行できる.これにより、デッドロックが回避されるため、サイクル待機条件が破壊される.