デッドロックとは何ですか?コードで説明してください。
デッドロックの概念:
2つまたは複数のスレッドが、ロックを占有することを前提として他のロックを取得します。これにより、スレッドは無限ループで待機し、デッドロックが発生します。
デッドロック状態:
デッドロックの必要条件
①相互に排他的な条件:プロセスによる割り当てられたリソースの排他的な使用を指します。つまり、特定のリソースが一定期間内に1つのプロセスによってのみ占有されます。この時点でリソースを要求している他のプロセスがある場合、リクエスターは、リソースを占有しているプロセスが使い果たされて解放されるまで待つことができます。
②リクエストアンドホールド条件:少なくとも1つのリソースを保持しているが、新しいリソースリクエストを行い、リソースがすでに他のプロセスによって占有されているプロセスを指します。この時点で、リクエストプロセスはブロックされていますが、保留中です。すでに取得している他のリソースに。
③非剥奪状態:プロセスが獲得したリソースを指します。使い果たされる前に剥奪することはできません。使い果たされた場合にのみ、単独で解放できます。
④ループ待機状態:デッドロックが発生した場合、プロセスが存在する必要があります。つまり、プロセスセット{P0、P1、P2、···、Pn}のリソースの循環チェーンが、によって占有されているリソースを待機しています。 P1; P1はP2によって占有されているリソースを待機しています...、PnはP0によって占有されているリソースを待機しています。
次のコードはデッドロックします
public class KillLock {
public static void main(String[] args) {
ManEatFood lk = new ManEatFood("李逵", 0);
ManEatFood sj = new ManEatFood("宋江", 1);
lk.start();
sj.start();
}
}
class HMilk{
}//牛奶
class CBread{
};//面包
class ManEatFood extends Thread{
String man;
int eat;
/**
* static修饰表示资源独一份
*/
static HMilk hMilk = new HMilk();
static CBread cBread = new CBread();
ManEatFood(String man,int eat){
this.man=man;
this.eat=eat;
}
@Override
public void run() {
try {
eatingFood();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void eatingFood() throws InterruptedException {
if (eat==0){
synchronized (hMilk){
System.out.println(this.man+"我渴了,准备喝牛奶!!");
Thread.sleep(1000);
synchronized (cBread){
System.out.println(this.man+"我饿了,我要吃面包!!");
}
}
}else{
synchronized (cBread){
System.out.println(this.man+"我饿了,我要吃面包!!");
Thread.sleep(2000);
synchronized (hMilk){
System.out.println(this.man+"我渴了,准备喝牛奶!!");
}
}
}
}
}
デッドロックの結果は次のとおりです。無限ループで待機しています。
デッドロックの解決策:
最も直接的な方法は、デッドロックの4つの条件を破壊することです。!次のように
デッドロックの解決策:
この状態を維持するために要求を中断すると、デッドロックの問題を解決できます。つまり、別の同期ロックを外部に配置できます。
デッドロックを処理した後の結果の図: