Вопрос с собеседования · Java

Что такое deadlock и как его предотвращать?

MiddleМногопоточность
Коротко

Deadlock — циклическое ожидание: поток A держит замок 1 и ждёт замок 2, поток B держит 2 и ждёт 1. Предотвращают единым порядком захвата, tryLock с таймаутом и откатом, короткими критическими секциями без вызова чужого кода под замком.

  • Четыре условия Коффмана: взаимное исключение, удержание с ожиданием, нет отбора, цикл
  • Найти — дамп потоков (jstack): «Found one Java-level deadlock»
  • Сам не разрешается: потоки стоят вечно

А ещё Livelock — потоки активны, но уступают друг другу без прогресса

Попробуйте сами

Взаимная блокировка двух потоков

Подробно

Классический пример — перевод денег:

void transfer(Account from, Account to, int sum) {
    synchronized (from) {
        synchronized (to) { ... }
    }
}
// поток 1: transfer(a, b)   поток 2: transfer(b, a) → взаимная блокировка

Условия взаимоблокировки (все четыре одновременно): ресурс используется монопольно; поток держит одно и ждёт другое; ресурс нельзя отобрать; ожидание образует цикл. Достаточно сломать любое.

Способы предотвращения:

  • глобальный порядок захвата — например, по id счёта: сначала меньший; цикла не возникнет;
  • tryLock с таймаутом (ReentrantLock): не получилось — отпустить захваченное и повторить позже;
  • не вызывать чужой код под замком — колбэк может захватить неизвестные замки;
  • один замок вместо нескольких, или структуры без блокировок.

Диагностика: jstack <pid> или дамп из VisualVM — JVM сама находит цикл среди мониторов и ReentrantLock и печатает, кто кого ждёт. Программно — ThreadMXBean.findDeadlockedThreads().

Родственные проблемы: livelock (потоки бесконечно уступают друг другу), starvation (поток никогда не получает ресурс).

Что хотят услышать

  • Определение и пример.
  • Условия возникновения.
  • Порядок захвата, tryLock, отсутствие чужого кода под замком.
  • Как найти в работающем приложении.

Частые ошибки

  • Надеяться, что JVM разорвёт взаимоблокировку сама.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Ситуация, когда поток бесконечно выполняет цикл и занимает всё процессорное время, а JVM потом сама разрешает её
  • ✗Нехватка памяти под стеки потоков
  • ✗Взаимная блокировка; лечится увеличением числа потоков в пуле до числа замков
  • ✓Взаимная блокировка; предотвращают единым порядком захвата и tryLock с таймаутом

Что спросят дальше

  • Как получить thread dump?
  • Чем deadlock отличается от livelock?

Разбор темы

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования