← Назад к вопросам
Будет ли утекать память при блокировке двух потоков, ожидающих мониторы друг друга?
3.0 Senior🔥 61 комментариев
#Многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Утечка памяти при deadlock двух потоков
Это интересный вопрос о взаимоблокировке (deadlock) и управлении памятью в Java. Давайте разберемся подробно.
Ответ: Нет, память не будет утекать
Когда два потока находятся в состоянии 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) {
// Поток 1: заблокирует lock1, затем будет ждать lock2
Thread thread1 = new Thread(() -> {
synchronized(lock1) {
System.out.println("Поток 1: захватил lock1");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized(lock2) {
System.out.println("Поток 1: захватил lock2");
}
}
});
// Поток 2: заблокирует lock2, затем будет ждать lock1
Thread thread2 = new Thread(() -> {
synchronized(lock2) {
System.out.println("Поток 2: захватил lock2");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized(lock1) {
System.out.println("Поток 2: захватил lock1");
}
}
});
thread1.start();
thread2.start();
// Здесь будет deadlock - потоки зависнут навсегда
}
}
Почему нет утечки памяти
1. Объекты остаются доступны из корней памяти
Даже при deadlock потоки остаются в памяти и доступны:
// Потоки все еще существуют в памяти
Thread thread1; // Referencing in JVM
Thread thread2; // Referencing in JVM
Object lock1; // Referenced by потоков
Object lock2; // Referenced by потоков
Монитор (встроенный в каждый объект в Java) не выделяет дополнительную память при блокировке. Это встроенная структура.
2. Память не освобождается, но это не утечка
Технически это скорее зависание ресурсов, а не утечка:
Утечка памяти = объект недостижим из корней, но не удален
Зависание ресурс = объект доступен, но не используется
Разница между утечкой и зависанием
public class MemoryLeakVsDeadlock {
// УТЕЧКА ПАМЯТИ - объект потерял все ссылки но не удалён
static class LeakExample {
static List<byte[]> cache = new ArrayList<>();
public void addToCache(byte[] data) {
cache.add(data); // объект добавлен и никогда не удалится
}
}
// DEADLOCK - объект доступен, но потоки зависли
static class DeadlockExample {
Object monitor1 = new Object();
Object monitor2 = new Object();
void methodA() {
synchronized(monitor1) {
synchronized(monitor2) { // Может deadlock
}
}
}
void methodB() {
synchronized(monitor2) {
synchronized(monitor1) { // Может deadlock
}
}
}
}
}
Ресурсы, которые МОГУТ утечь при deadlock
Хотя сама память не утекает, могут утечь другие ресурсы:
public class DeadlockWithResourceLeak {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized(lock1) {
// Открыли файл или соединение
FileInputStream fis = null;
try {
fis = new FileInputStream("file.txt");
Thread.sleep(1000);
synchronized(lock2) { // DEADLOCK случится здесь
fis.read();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// Это никогда не выполнится при deadlock!
try { fis.close(); } catch (Exception e) {}
}
}
});
Thread thread2 = new Thread(() -> {
synchronized(lock2) {
Thread.sleep(500);
synchronized(lock1) { // DEADLOCK
}
}
});
thread1.start();
thread2.start();
// Файл останется открытым - утечка РЕСУРСОВ, не памяти!
}
}
Как обнаружить deadlock
# JDK 19+
jps -l # Найди PID приложения
jstack <PID> | grep -i dead # Поищи deadlock информацию
// Программно проверить deadlock
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long[] deadlocked = bean.findDeadlockedThreads();
if (deadlocked != null && deadlocked.length > 0) {
System.out.println("DEADLOCK ОБНАРУЖЕН!");
for (ThreadInfo info : bean.getThreadInfo(deadlocked)) {
System.out.println("Заблокированный поток: " + info.getThreadName());
}
}
Итог
- Память НЕ утечет при deadlock - объекты и потоки остаются в памяти и доступны для GC
- Ресурсы МОГУТ утечь - файлы, соединения, если они открыты до deadlock
- Процесс зависнет - будет занимать CPU и памяти, но это не утечка
- Используй try-with-resources для предотвращения утечки ресурсов
- Избегай nested synchronized - используй Lock или ReentrantLock с timeout