Kotlin:调用 CoroutineScope.launch 与在协程内启动之间的区别

var*_*nkr 4 kotlin kotlin-coroutines coroutinescope structured-concurrency

我试图理解 Kotlin 中的结构化并发,但无法理解这段代码。

fun main(): Unit = runBlocking {
    other(this)
}

suspend fun other(scope: CoroutineScope) {
    val job = scope.launch {
        scope.launch {
            delay(200)
            println("e")
        }
        println("a")
    }
    job.invokeOnCompletion {
        println("Complete")
    }
}
Run Code Online (Sandbox Code Playgroud)

代码打印出来

a
Complete
e
Run Code Online (Sandbox Code Playgroud)

如果我用 替换内部scope.launch调用launch,就像这样

suspend fun other(scope: CoroutineScope) {
    val job = scope.launch {
       launch {
            delay(200)
            println("e")
        }
        println("a")
    }
    job.invokeOnCompletion {
        println("Complete")
    }
}
Run Code Online (Sandbox Code Playgroud)

它打印

a
e
Complete
Run Code Online (Sandbox Code Playgroud)

这表明第一个示例不遵循结构化并发,因为父作业先于子作业完成。我的困惑是,为什么会发生这种情况?

我觉得在这种情况下scope.launch可能相当于调用launch(应该相当于this.launch并且 this 指的是scope)。但似乎这不是真的。有人可以解释为什么第一个会导致非结构化并发以及两个启动调用之间有什么区别吗?谢谢!

小智 7

在第一个代码中,虽然内部启动看起来像是外部启动的子级,但实际上不是——它是外部启动的同级,因为它们都是从同一范围启动的。因此,等待外部启动的工作完成并不需要等待内部启动的工作。

第二个代码使用结构化并发,因为内部启动使用外部启动(启动块的接收者)创建的范围。在这种情况下,它是外部启动的子项,因此等待外部作业完成也会等待子项完成。

第二个是你应该做的:使用启动块的 CoroutineScope 接收器来启动子作业。使用其他范围并不能提供结构化并发。