Kotlin协程执行顺序差异解析:移除CoroutineScope为何改变结果?
问题解析:Kotlin协程中
coroutineScope与直接launch的执行差异 先基于你的描述还原两段核心代码:
第一段代码(带第一个coroutineScope)
fun main() = runBlocking { println("Start") // 第一个coroutineScope包裹launch coroutineScope { launch { delay(100) println("Hello") } } // 后续逻辑 coroutineScope { launch { delay(100) println("World1") } launch { delay(100) println("World2") } } println("Done") }
输出顺序:Start → Hello → World1/World2 → Done
第二段代码(移除第一个coroutineScope)
fun main() = runBlocking { println("Start") // 直接启动launch,无coroutineScope包裹 launch { delay(100) println("Hello") } // 后续逻辑 coroutineScope { launch { delay(100) println("World1") } launch { delay(100) println("World2") } } println("Done") }
输出顺序:Start → Hello/World1/World2 → Done(你描述的Hello先于Start可能是代码顺序调整,但核心差异是并行执行逻辑)
核心原因:coroutineScope的挂起等待特性
coroutineScope是挂起函数:调用它时,当前协程会被挂起,直到coroutineScope内部所有子协程(这里就是那个launch)全部执行完毕,才会恢复当前协程的执行。所以第一段代码中,println("Start")执行后,进入coroutineScope启动子协程打印Hello,当前协程会一直等待这个子协程完成,才会继续执行后面的coroutineScope和println("Done"),因此Hello一定在World1/World2之前。- 直接调用
launch:launch只是在当前协程作用域(这里是runBlocking的根作用域)启动一个子协程,它不会挂起当前协程。当前协程会立刻继续执行后面的coroutineScope(而这个coroutineScope又会挂起等待它的子协程)。此时,第一个launch的子协程和后面coroutineScope里的子协程是并行执行的,所以Hello可能和World1/World2同时或先后输出,而非严格顺序。
关于Job状态的猜测补充
你的猜测方向是对的,coroutineScope的行为本质和Job绑定:coroutineScope会创建一个新Job,这个Job会等待所有子Job(子协程的Job)完成后才进入完成状态。当coroutineScope的Job未完成时,当前协程会挂起等待。而直接launch创建的子Job是根作用域Job的子Job,根作用域(runBlocking)会等待所有子Job完成,但当前协程本身不会被launch挂起,所以会继续向下执行。
内容的提问来源于stack exchange,提问作者Charles
相关产品推荐
相关产品推荐

