← Назад к вопросам

Отменятся ли дочерние корутины при отмене родительской

3.0 Senior🔥 171 комментариев
#Многопоточность и асинхронность

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Отмена дочерних корутин при отмене родительской

Да, в Kotlin Coroutines дочерние корутины автоматически отменяются при отмене родительской корутины. Это одно из фундаментальных свойств иерархической структуры корутин, обеспечивающее корректное управление жизненным циклом и ресурсами.

Механизм иерархической отмены

Когда вы запускаете корутину внутри другой корутины (например, с помощью launch или async в рамках coroutineScope или supervisorScope), между ними устанавливается отношение родитель-SD-ребёнок. При отмене родительской корутины:

  1. Родительская корутина немедленно переходит в состояние отмены (Cancelling).
  2. Все её непосредственные дочерние корутины рекурсивно получают сигнал об отмене.
  3. Родительская корутина ожидает завершения всех дочерних корутин (их отмены или нормального завершения) перед тем как перейти в состояние отменена (Cancelled).

Практический пример

Рассмотрим код, демонстрирующий это поведение:

import kotlinx.coroutines.*

fun main() = runBlocking {
    val parentJob = launch {
        println("Родительская корутина начата")
        
        launch {
            println("Дочерняя корутина 1 начата")
            delay(3000)
            println("Дочерняя корутина 1 завершена") // Не будет выполнено
        }
        
        launch {
            println("Дочерняя корутина 2 начата")
            delay(5000)
            println("Дочерняя корутина 2 завершена") // Не будет выполнено
        }
        
        delay(1000)
        println("Родительская корутина завершена")
    }
    
    delay(500)
    println("Отменяем родительскую корутину")
    parentJob.cancel() // Отменяем родительскую корутину
    parentJob.join()
    println("Программа завершена")
}

Результат выполнения:

Родительская корутина начата
Дочерняя корутина 1 начата
Дочерняя корутина 2 начата
Отменяем родительскую корутину
Программа завершена

Как видно, ни одна из дочерних корутин не достигает своих завершающих сообщений, поскольку они были отменены вместе с родительской.

Важные нюансы и исключения

  1. Использование SupervisorJob: Если дочерняя корутина запущена в контексте SupervisorJob или с использованием supervisorScope, отмена одной дочерней корутины не влияет на другие дочерние корутины, и отмена родительской корутины также приводит к отмене всех дочерних.
import kotlinx.coroutines.*

fun main() = runBlocking {
    val parentJob = launch(SupervisorJob()) {
        println("Родитель с SupervisorJob начат")
        
        launch {
            println("Дочерняя 1 начата")
            delay(3000)
            println("Дочерняя 1 завершена")
        }
        
        launch {
            println("Дочерняя 2 начата")
            delay(1000)
            throw RuntimeException("Ошибка в дочерней 2") // Не отменяет другие дочерние
        }
        
        delay(2000)
    }
    
    delay(1500)
    parentJob.cancel() // Всё равно отменяет все дочерние корутины
    parentJob.join()
}
  1. Корутины в другом контексте: Если дочерняя корутина запущена с явно указанным контекстом, не являющимся дочерним по отношению к родительской, иерархическая отмена может не сработать:
import kotlinx.coroutines.*

fun main() = runBlocking {
    val parentJob = launch {
        println("Родитель начат")
        
        // Эта корутина НЕ будет автоматически отменена при отмене родителя
        launch(Job()) { // Явно созданный Job, не связанный иерархически
            println("Изолированная корутина начата")
            delay(3000)
            println("Изолированная корутина завершена") // Будет выполнено!
        }
        
        delay(1000)
        println("Родитель завершён")
    }
    
    delay(500)
    parentJob.cancel()
    delay(3500) // Ждём завершения изолированной корутины
}
  1. Обработка отмены: Дочерние корутины должны корректно реагировать на отмену. Функции приостановки Kotlin Coroutines (like delay, withContext, etc.) проверяют статус отмены и выбрасывают CancellationException, но в CPU.
Отменятся ли дочерние корутины при отмене родительской | PrepBro