Kotlin:调用CoroutineScope.launch与在协同程序内部调用launch的区别

gkn4icbw  于 2023-01-02  发布在  Kotlin
关注(0)|答案(1)|浏览(251)

我正在尝试理解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")
    }
}

代码打印

a
Complete
e

如果我用launch替换内部的scope.launch调用,如下所示

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

它打印

a
e
Complete

这表明第一个例子没有遵循结构化并发,因为父作业在子作业之前完成。我的困惑是,为什么会发生这种情况?
我觉得scope.launch在这种情况下可能等同于调用launch(应该等同于this.launch,这里指的是scope)。但似乎不是这样。有人能解释一下为什么第一个会导致非结构化并发,以及两个启动调用之间的区别吗?谢谢!

euoag5mw

euoag5mw1#

在第一段代码中,虽然内部启动看起来像是外部启动的子进程,但实际上它不是--它是外部启动的兄弟进程,因为它们都是从同一个作用域启动的。因此,等待外部启动的任务完成并不是等待内部启动。
第二段代码使用结构化并发,因为内部启动使用外部启动(启动块的接收者)创建的作用域,在这种情况下,它是外部启动的子作业,因此等待外部作业完成也要等待子作业完成。
第二个是你应该做的:使用启动块的CoroutineScope接收器来启动子作业。2使用其他作用域并不能提供结构化并发。

相关问题