Как бороться с дедлоком
Что проверяют
Знаете ли вы, откуда берётся взаимная блокировка и как она выглядит именно в Android: зависший главный поток и ANR. Следом обычно спрашивают, как вы нашли бы дедлок в продакшене и чем здесь опасны корутины.
Как отвечать
Дедлок возникает, когда одновременно выполнены четыре условия Коффмана: взаимное исключение, удержание ресурса с ожиданием другого, отсутствие принудительного отъёма и циклическое ожидание. Достаточно разрушить любое одно.
Способы, которые работают на практике:
- единый порядок захвата: если два потока берут замки
AиB, оба берут их в одном порядке, и цикла не возникает; - ожидание с таймаутом:
ReentrantLock.tryLock(timeout, unit)вместоsynchronized, при неудаче поток отпускает то, что держит, и повторяет попытку; - короткие критические секции: внутри замка не вызывать чужой код, колбэки и сеть;
- ограничение потоком: состояние меняется только в одном потоке или на
Dispatchers.Default.limitedParallelism(1), тогда замки не нужны вовсе. Сюда же относится обмен сообщениями черезChannel.
Android-специфика, без которой ответ неполный:
- главный поток: если он ждёт фоновую задачу, а та через
HandlerилиDispatchers.Mainждёт главный поток, приложение висит, а через несколько секунд система показывает ANR; runBlockingна главном потоке: классический способ получить такую взаимоблокировку с корутинами;Mutexиз kotlinx.coroutines: он нереентерабельный, повторныйlock()в той же корутине блокирует её навсегда.
Найти дедлок помогают дамп потоков в отладчике Android Studio, трассы ANR из bugreport и Android vitals в Play Console: видно, какой поток что держит и чего ждёт.
Где спотыкаются
Пересказывают теорию операционных систем и ни слова не говорят про главный поток и ANR. Для Android-разработчика это главное проявление проблемы.
Предлагают «убить один из потоков». В Java так нельзя: Thread.stop() давно объявлен устаревшим, а на Android просто бросает исключение.
Путают дедлок с гонкой данных или livelock. При гонке потоки работают и портят данные, при livelock крутятся без прогресса, а при дедлоке стоят и ничего не делают.