デッドロックがどのように作成されるかを理解しようとしています。2 つの同期メソッドで 2 つのスレッドを使用すると、デッドロックが発生する可能性があることを理解しました。ネットからの多くの例を調べました。
待機と通知でデッドロックを作成できますか? スレッドが待機中になるたびに、通知されます。では、これはどのようにしてデッドロックに陥るのでしょうか?
例のイラストが役に立ちます。
Deadlock is caused when two threads try to obtain the same, multiple locks in different order:
// T1
synchronized (A) {
synchronized (B) {
// ...
}
}
// T2
synchronized (B) {
synchronized (A) {
// ...
}
}
デッドロックを防ぐ唯一の方法は、すべてのスレッドが同じ順序でロックを取得するようにすることです。すべてのスレッドが A の次に B を実行するか、すべてのスレッドが B の次に A を実行するかのいずれかです。
複数のロックがない場合、デッドロックはありません。ただし、スレッドの枯渇や、デッドロックに似たその他の問題が発生する可能性があります。
スレッド 1 がメソッド A の同期ブロックに入り、待機するとします。次に、スレッド 2 はメソッド A で同期ブロックに入ろうとします。スレッド 1 は通知を待っており、スレッド 2 は同期ブロックで待機しています。すべてが今待っています。他のスレッドは、スレッド 1 が待機しているオブジェクトに通知する必要があります。これは、デッドロックを引き起こすシナリオの 1 つにすぎません。それを行うにはあらゆる種類の方法があります。
待機中のスレッドは、何らかのコードで明示的に通知されない限り、通知されません。したがって、あなたが探している例は絶対に簡単です:
public static void main(String[] args) {
synchronized(String.class) {
String.class.wait();
}
}
これは永久にハングアップします。ただし、技術的には、デッドロックではありません。デッドロックでは、各スレッドが次のブロックを解除するまで待機するクローズド サイクルに関与する 2 つ以上のスレッドが必要です。
デッドロックの待機/通知に近いもの:
public class Example
{
volatile boolean isNotified = false;
public synchronized void method1() {
try
{
isNotified = false;
while (!isNotified)
wait();
notifyAll();
System.out.println("Method 1");
} catch (InterruptedException e) {/*NOP*/}
}
public synchronized void method2() {
try {
isNotified = true;
while (isNotified)
wait();
notifyAll();
System.out.println("Method 2");
} catch (InterruptedException e) {/*NOP*/}
}
public static void main(String[] args)
{
Example example = new Example();
Thread thread1 = new Thread()
{
public void run()
{
example.method1();
}
};
Thread thread2 = new Thread()
{
public void run()
{
example.method2();
}
};
thread1.start();
thread2.start();
}
}