Отмена, ошибки и structured concurrency
Кто владеет работой, кто отменяет соседей и где ловить ошибку
Работа принадлежит области
suspend разрешает приостановку, но не назначает фоновый поток. Дочерняя работа принадлежит своему Job: обычная ошибка ребёнка отменяет родителя и соседей. В supervisorScope сбой ребёнка не отменяет остальных автоматически; обработка ошибки всё равно нужна. Ошибка самого блока supervisorScope отменяет его детей. Kotlin: исключения корутин.
Отмена — кооперативный протокол
CPU-цикл без проверок может продолжать работу после cancel. Вызывайте currentCoroutineContext().ensureActive() в разумных точках. Произвольная suspend-функция не обязана ни приостанавливаться, ни проверять отмену. ensureActive.
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.ensureActive
suspend fun sum(values: IntArray): Long {
var total = 0L
for (value in values) {
currentCoroutineContext().ensureActive()
total += value
}
return total
}
Выбор диспетчера делает вызывающий код или явно выделенная вычислительная граница.
Не превращайте отмену в ошибку сети
При широком catch (Exception) сначала пробрасывайте CancellationException. CoroutineExceptionHandler наблюдает необработанное исключение, но не возобновляет упавшую корутину. Ошибку async получают через await; в обычной иерархии родитель может отмениться ещё до await. Kotlin: исключения корутин.
Mutex защищает составную операцию и при ожидании не блокирует поток. Он не реентерабелен: повторный lock под уже удерживаемой блокировкой способен навсегда приостановить работу. Потокобезопасность отдельного get/set не делает атомарным read-modify-write. Mutex.
Основа отбора: draft/coroutines.md, draft/M++.md, draft/lifeconding.md.