記事を理解するために必要な知識のレベル: Java 構文と Java コアのクエストを完了し、現在 Java マルチスレッドを学習中です。デッドロックまたは Java のデッドロック、またはデッドロックは、スレッドが同期されたオブジェクトのペアに対して循環依存関係を持っている場合に発生するエラーです。1 つのスレッドがオブジェクト モニターに入り
この場合、両方のスレッドがブロックされ、それぞれが他方のロックを解放するのを待機します。しかし、これを行うにはメソッドを完了する必要があり、別のスレッドによってブロックされているため、誰もこれを実行しません。それで彼らはそれが起こった場所で立ち往生しました
x
、もう 1 つのスレッドがオブジェクト モニターに入ると想像してくださいy
。オブジェクト内のスレッドがx
そのオブジェクトの同期メソッドを呼び出そうとしy
、y
同時にそのオブジェクトがそのオブジェクトの同期メソッドを呼び出そうとした場合x
、スレッドは待機状態になってしまいます。以下は、デッドロックなどの概念に関する Java ドキュメント チュートリアルの例です。スレッドのブロックはどこで発生しますか?
public class Deadlock {
static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public synchronized void bow(Friend bower) {
System.out.format("%s: %s" + " has bowed to me!%n", this.name, bower.getName());
bower.bowBack(this);
}
public synchronized void bowBack(Friend bower) {
System.out.format("%s: %s"
+ " has bowed back to me!%n",
this.name, bower.getName());
}
}
public static void main(String[] args) {
final Friend alphonse =
new Friend("Alphonse");
final Friend gaston =
new Friend("Gaston");
new Thread(new Runnable() {
@Override
public void run() {
// System.out.println("Thread 1");
alphonse.bow(gaston);
// System.out.println("Th: gaston bowed to alphonse");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// System.out.println("Thread 2");
gaston.bow(alphonse);
// System.out.println("2.gaston waiting alph bowed");
}
}).start();
}
}
ここで理解すべき重要な点が 2 つあります。
- 同時に実行されている各スレッドは正確に何をするのでしょうか?
- どのようなロックが使用されていますか?
Friend
:alphonse
との 2 つのオブジェクトを作成したとしますgaston
。それぞれに独自のロックがあります。したがって、これらのロックにはジゴロとガストンの 2 つがあります。オブジェクトの同期メソッドに入るとそのロックはロックされ、メソッドが終了すると解放 (またはロック解除) されます。次にスレッドについてです。最初のスレッドを名前を付けますAlphonse
(オブジェクト alphonse と区別するために大文字を付けます)。A
これが何を行うかは次のとおりです (の略で と呼びましょうAlphonse
):
A: alphonse.bow(gaston) — получает лок alphonse;
A: gaston.bowBack(alphonse) — получает лок gaston;
A: возвращается из обоих методов, тем самым освобождая лок.
そして、現時点でスレッドが行っていることは次のとおりですGaston
。
G: gaston.bow(alphonse) — получает лок gaston;
G: alphonse.bowBack(gaston) — получает лок alphonse;
G: возвращается из обоих методов, тем самым освобождая лок.
では、このデータをまとめて答えを導き出しましょう。スレッドはさまざまな順序で絡み合う (つまり、スレッドのイベントが発生する) 可能性があります。たとえば、次のような順序の場合、デッドロックは機能します。
A: alphonse.bow(gaston) — получает лок alphonse
G: gaston.bow(alphonse) — получает лок gaston
G: пытается вызвать alphonse.bowBack(gaston), но блокируется, ожидая лока alphonse
A: пытается вызвать gaston.bowBack(alphonse), но блокируется, ожидая лока gaston
deadlock
。ただし、別のウィーブも可能です。この場合、スレッドの 1 つが完了するまでに 2 番目のスレッドが開始する前に時間がかかります。
A: alphonse.bow(gaston) — получает лок alphonse
A: gaston.bowBack(alphonse) — получает лок gaston
A: возвращается из обоих методов, открывая оба лока
G: gaston.bow(alphonse) — получает лок gaston
G: alphonse.bowBack(gaston) — получает лок alphonse
G: возвращается из обоих методов, открывая оба лока
この場合、スレッドの相互ブロックは発生しません。たとえば、別のスレッドが実行できるようにするメソッドが追加されました。結果が同時に発生するイベントの順序 (計画された順序または実行速度) に依存する場合、そのようなプロセスはロシア語で競合状態 (「競合状態」) と呼ばれます。すべての競合状態が潜在的にデッドロックを引き起こすわけではありませんが、私の経験では、競合状態のみがデッドロックを引き起こします。 投稿者: デイブ・リレサン
他に読むべきもの: |
---|
Java 開発者グループ: |
GO TO FULL VERSION