Ответ вслух Senior Корутины и structured concurrency обновлено

Как работает отмена корутин

Вопрос

Расскажи подробно, как работает отмена корутин и какие ошибки с ней делают.

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

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Отмена в корутинах кооперативная. Вызов job.cancel() ничего не прерывает силой: он переводит Job в состояние отмены и отменяет детей.

Что должно прозвучать в ответе

  • cancel() переводит Job в Cancelling, реальная остановка в точке приостановки

  • Отмена кооперативная: в циклах isActive, ensureActive, yield

  • Реализована через CancellationException, его нельзя глотать

  • Отмена распространяется на детей

  • NonCancellable для очистки в finally

  • withTimeout бросает TimeoutCancellationException

Что могут спросить следом

  • Почему runCatching в корутинах опасен?
  • Как отменить блокирующий вызов, например чтение сокета?
  • Чем withTimeout отличается от withTimeoutOrNull?

Разбор

Отмена в корутинах кооперативная. Вызов job.cancel() ничего не прерывает силой: он переводит Job в состояние отмены и отменяет детей. Сама корутина остановится, когда дойдёт до точки приостановки, потому что suspend-функции из kotlinx.coroutines проверяют отмену и бросают CancellationException. Если корутина крутит вычислительный цикл без suspend-вызовов, она отмену не заметит, поэтому в таких циклах проверяют isActive или вызывают ensureActive(). Блокирующие вызовы вроде чтения сокета отмена тоже не прервёт, их закрывают вручную или через runInterruptible. Поскольку отмена это исключение, его нельзя глотать: catch (e: Exception) или runCatching вокруг suspend-кода перехватят его, и отменённая корутина продолжит работу. Правильно ловить конкретные типы или перебрасывать CancellationException. В finally после отмены suspend-функции сразу бросят исключение, поэтому для очистки используют withContext(NonCancellable). Таймауты устроены так же: withTimeout бросает TimeoutCancellationException, withTimeoutOrNull возвращает null.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.