You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何含SupervisorJob的协程作用域会取消子协程?求逻辑解析

为什么使用SupervisorJob的协程作用域会取消子launch任务?

我不需要解决方法,只想理解逻辑——毕竟SupervisorJob本不应取消子协程。

代码示例

suspend fun main() {
    val scope = CoroutineScope(SupervisorJob())
    scope.launch {
        launch { f1() }
        launch { f2() }
        launch { error() }
    }
}   

suspend fun f1() {
    delay(300)
    println("f1")
}

suspend fun f2() {
    delay(300)
    println("f2")
}

运行结果

无任何输出,且错误未抛出。

补充疑问

若改为以下写法则正常,这是为什么?

scope.launch { .. }
scope.launch { .. }
scope.launch { .. }

逻辑解释

核心差异在于协程的层级关系和Job类型:

  1. 第一种写法的问题:

    • 你在scope.launch创建的协程内部,又启动了三个子launch。这个外层的scope.launch默认使用普通Job(不是SupervisorJob),它是三个内部launch的直接父Job。
    • 普通Job的特性是:一旦子Job失败,会立即取消自身以及所有其他子Job。所以error()抛出异常后,外层的scope.launch协程被取消,连带取消了执行f1()和f2()的两个子launch,导致没有输出。
    • 同时,协程的异常默认会被内部异常处理器捕获,不会向上抛出到main函数,所以看不到错误信息。
  2. 第二种写法的正常原因:

    • 三个scope.launch直接挂载在CoroutineScope(SupervisorJob())下,它们的直接父Job是SupervisorJob。
    • SupervisorJob的核心特性是子Job失败不会影响同级其他子Job:当其中一个launch抛出异常时,只会取消该异常launch自身的子树(这里没有子树),不会影响另外两个执行f1()和f2()的协程,所以它们能正常执行并输出结果。

内容的提问来源于stack exchange,提问作者senior salaga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 16:14:57