Ответ
Классический deadlock возникает, когда два или более потока блокируют разные ресурсы и каждый ждет освобождения ресурса, захваченного другим. Гарантированный deadlock можно создать, нарушив принцип упорядочивания блокировок и добавив задержку для синхронизации состояния потоков.
Пример кода, моделирующего deadlock:
public class GuaranteedDeadlock {
private static final Object LockA = new Object();
private static final Object LockB = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (LockA) { // 1. Поток 1 захватывает LockA
System.out.println("Thread 1: Holding Lock A...");
try {
Thread.sleep(50); // Задержка для гарантии, что оба потока захватят свои первые блокировки
} catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for Lock B...");
synchronized (LockB) { // 3. Поток 1 пытается захватить LockB (но он у Thread 2) -> БЛОКИРОВКА
System.out.println("Thread 1: Acquired both locks!"); // Эта строка никогда не выполнится
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (LockB) { // 2. Поток 2 захватывает LockB
System.out.println("Thread 2: Holding Lock B...");
try {
Thread.sleep(50);
} catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for Lock A...");
synchronized (LockA) { // 4. Поток 2 пытается захватить LockA (но он у Thread 1) -> БЛОКИРОВКА
System.out.println("Thread 2: Acquired both locks!"); // Эта строка никогда не выполнится
}
}
});
thread1.start();
thread2.start();
// Оба потока теперь заблокированы навсегда.
}
}
Почему deadlock гарантирован:
- Разный порядок блокировок: Thread 1 берет
LockA, затемLockB. Thread 2 беретLockB, затемLockA. - Синхронизация через
sleep(): Задержка дает время каждому потоку захватить свой первый монитор до того, как они попытаются захватить второй. - Циклическое ожидание: Каждый поток удерживает ресурс, нужный другому, и ждет, создавая неразрешимую циклическую зависимость.
Для обнаружения deadlock во время выполнения можно использовать jstack или JMX (ThreadMXBean.findDeadlockedThreads()).