Ответ
Нет, deadlock сам по себе не вызывает утечку памяти (memory leak), но приводит к зависанию программы (liveness failure).
Почему нет утечки? Утечка памяти — это ситуация, когда объекты больше не нужны, но остаются достижимыми для GC, занимая память. В deadlock'е потоки заблокированы навсегда, но ссылки на объекты (в том числе на объекты-мониторы) остаются активными и легитимными — они находятся в стеках заблокированных потоков. Эти объекты по-прежнему достижимы, поэтому GC их не соберет, но это не считается утечкой, так как они являются частью рабочего состояния приложения (хоть и некорректного).
Пример классического deadlock:
final Object lock1 = new Object();
final Object lock2 = new Object();
Thread t1 = new Thread(() -> {
synchronized (lock1) { // t1 захватывает lock1
Thread.sleep(100);
synchronized (lock2) { } // t1 ждет lock2, который у t2
}
});
Thread t2 = new Thread(() -> {
synchronized (lock2) { // t2 захватывает lock2
Thread.sleep(100);
synchronized (lock1) { } // t2 ждет lock1, который у t1
}
});
t1.start();
t2.start();
// Оба потока заблокированы навсегда.
Основные проблемы deadlock:
- Отказ в обслуживании: Потоки не могут прогрессировать.
- Блокировка ресурсов: Захваченные ресурсы (соединения, файлы) не освобождаются.
Способы предотвращения:
- Упорядочивание блокировок: Всегда захватывайте несколько блокировок в одном и том же глобальном порядке.
- Использование
tryLockс таймаутом из пакетаjava.util.concurrent.locks. - Статический анализ кода для выявления потенциальных deadlock'ов.