Вопрос проверяет понимание одной из самых опасных проблем многопоточности и причин её возникновения.
Deadlock — это ситуация, когда два или более потоков навсегда блокируют друг друга. Каждый поток удерживает ресурс и ждёт ресурс, занятый другим потоком. В результате ни один поток не может продолжить выполнение. Программа при этом не падает, а просто «зависает».
Deadlock относится к логическим ошибкам многопоточности и часто проявляется только в продакшене.
Deadlock — это состояние, при котором несколько потоков находятся в бесконечном ожидании ресурсов, удерживаемых друг другом.
Рассмотрим типичную ситуацию:
Поток A захватил монитор объекта lock1
Поток B захватил монитор объекта lock2
Поток A ждёт lock2
Поток B ждёт lock1
Ни один из потоков не может продолжить работу.
synchronized (lock1) {
// ...
synchronized (lock2) {
// ...
}
}
Deadlock возможен, если одновременно выполняются условия:
Взаимное исключение
Удержание и ожидание
Отсутствие принудительного освобождения
Циклическое ожидание
DeadlockНа практике используют несколько подходов:
Фиксированный порядок захвата блокировок
Минимизация количества synchronized-блоков
Использование tryLock()
Проектирование без shared state
Deadlock — это критическая ошибка многопоточности, которую проще предотвратить архитектурно, чем обнаружить и исправить.