デッドロックに関しては、誰もが共通の理解を持っています。デッドロックは、リソースを求めて競争したいが、残念ながら諦めず、プログラムの実行に失敗する、一種の待機です。スレッドのデッドロックは常に気分が良くなりますが、実際に説明すると、そこから何を言うべきかわかりません。インタビュアーがデッドロックを書くように頼むことがあります。デッドロックを書く場合は、理解する必要がありますが、急いで書いてください。どこから始めればいいのかわからないようです。今日は、プログラムをクラッシュさせるためのデッドロックを作成します。
1.同期された実装を使用する
package com.example.demoproject;
public class DeadThread implements Runnable{
private Object lock1 = new Object() ;
private Object lock2 = new Object() ;
public void method() throws Exception{
System.out.println("死锁开始~~~");
synchronized (lock1){
System.out.println(Thread.currentThread().getName()+":锁住了lock1");
Thread.sleep(1000);
synchronized (lock2){
System.out.println(Thread.currentThread().getName()+":锁住了lock2");
}
}
}
public void otherMethod() throws Exception{
System.out.println();
synchronized (lock2){
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+":锁住了lock2");
synchronized (lock1){
System.out.println(Thread.currentThread().getName()+":锁住了lock1");
}
}
}
@Override
public void run() {
try {
method();
otherMethod();
} catch (Exception e) {
}
}
public static void main(String[] args) {
DeadThread deadThread = new DeadThread();
new Thread(deadThread,"线程A").start();
new Thread(deadThread,"线程B").start();
}
}
メソッドメソッドはlock1をロックしてからlock2をロックします。もちろん、途中で待機し、otherMethodがlock2をロックするのを待ちます。それ以外の場合、メソッドが実行され、otherMethodが再度ロックされ、デッドロックは発生しません。ここでのスリープ待機は、同時実行性が高い場合にスレッドがリソースをプリエンプトするときに発生する可能性のある状況をシミュレートするためのものです。
よく見てみると、実際、これはあまり良くありません。Method()とotherMethod()はそれぞれスレッドによって開始され、デッドロックが発生する可能性があります。スレッドを1つ少なく、Runnableを1つ少なくするために、直接それらを下に置きます。 runメソッドは実際には少し冗長です。以下では、最もトラブルのない方法でデッドロックを直接記述します。もちろん、コードはトラブルを回避しますが、ロックはトラブルを回避しません。デッドロックを実現することは、操作のロックを解除せずに同期するための最も便利な方法です。
2.ReentrantLockを使用してロックします
public class DeadThreadLock {
private static Lock lock1 = new ReentrantLock() ;
private static Lock lock2 = new ReentrantLock() ;
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
try {
lock1.lock();
System.out.println(Thread.currentThread().getName()+"lock1加锁成功");
Thread.sleep(1000);
lock2.lock();
System.out.println(Thread.currentThread().getName()+"lock1,2加锁成功");
lock1.unlock();
lock2.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"线程A").start();
new Thread(new Runnable() {
@Override
public void run() {
try {
lock2.lock();
System.out.println(Thread.currentThread().getName()+"lock2加锁成功");
Thread.sleep(1000);
lock1.lock();
System.out.println(Thread.currentThread().getName()+"lock1,2加锁成功");
lock1.unlock();
lock2.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"线程B").start();
}
}
コードは非常に単純です。つまり、2つのロックが競合し、スレッドAがlock1を占有し、スレッドBがlock2を占有し、スレッドBがスレッドAがlock1のブロッキングキューでlock1を解放するのを待ち、スレッドAがスレッドBが解放されるのを待ちます。 lock2のブロッキングキューにあるlock2、目を刺したいのですが、残念ながら、私は死んでいます、おっと、立ち往生しています、いつも恥ずかしいです、ハハ。興味があれば、書き留めて自分で試すことができます。デッドロックを解決する方法はたくさんありますが、デッドロックを作成するのは簡単ではありませんか?ハハ、私たちはみんな問題を起こすことができる人です!!
犠牲も勝利もありません〜