Ответ
Deadlock (взаимная блокировка) — это ситуация, когда два или более потока находятся в состоянии бесконечного ожидания ресурсов, захваченных друг другом.
Условия возникновения Deadlock (Коффмана):
- Взаимное исключение: Ресурс не может быть использован более чем одним потоком одновременно.
- Удержание и ожидание: Поток, удерживая один ресурс, запрашивает другой.
- Отсутствие вытеснения: Ресурс может быть освобожден только добровольно удерживающим его потоком.
- Циклическое ожидание: Существует круговая цепочка потоков, каждый из которых ждет ресурс, удерживаемый следующим в цепочке.
Пример классического Deadlock на двух объектах-блокировках:
public class DeadlockExample {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
synchronized (lock1) { // 1. threadA захватывает lock1
System.out.println("Thread A: Holding lock 1...");
try { Thread.sleep(10); } // Имитация работы
catch (InterruptedException e) {}
System.out.println("Thread A: Waiting for lock 2...");
synchronized (lock2) { // 3. threadA пытается захватить lock2 (но его удерживает threadB)
System.out.println("Thread A: Acquired lock 1 & 2!");
}
}
});
Thread threadB = new Thread(() -> {
synchronized (lock2) { // 2. threadB захватывает lock2
System.out.println("Thread B: Holding lock 2...");
try { Thread.sleep(10); } // Имитация работы
catch (InterruptedException e) {}
System.out.println("Thread B: Waiting for lock 1...");
synchronized (lock1) { // 4. threadB пытается захватить lock1 (но его удерживает threadA)
System.out.println("Thread B: Acquired lock 2 & 1!");
}
}
});
threadA.start();
threadB.start();
// Оба потока заблокируются навсегда, ожидая друг друга.
}
}
Как избежать Deadlock?
- Упорядочивание блокировок (всегда захватывать
lock1, затемlock2). - Использование
tryLock()изjava.util.concurrent.locks.ReentrantLockс таймаутом. - Тщательный анализ и проектирование многопоточного кода.