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

Kotlin不同作用域下协程执行顺序差异原因咨询

Kotlin协程执行顺序差异的原因解析

核心差异源于单线程调度器下的协程调度顺序,结合coroutineScope的挂起等待特性和launch的非阻塞调度特性,我们可以拆解两个场景的执行流程:

前提说明

runBlocking默认使用单线程调度器,所有协程任务都在同一个线程上执行,调度器会按任务加入队列的先后顺序处理可执行的协程。


结果A的执行流程

  1. 第一个coroutineScope:内部无launch,所有代码都是同步执行的挂起逻辑,直接顺序输出:
    in the coroutineScope 1 
    coroutineScope inside the coroutineScope1
    
  2. 第二个coroutineScope:
    • 先执行同步代码println("in the coroutineScope 2"),输出该行。
    • 调用launch,将该协程任务加入调度队列。
    • coroutineScope挂起,等待所有子协程完成。此时调度器无其他待处理任务,立即执行刚加入的launch协程:
      • 打印coroutine in the coroutineScope 2
      • 内部嵌套的coroutineScope同步执行,打印coroutineScope inside the coroutineScope2 coroutine
    • 子协程全部完成,coroutineScope恢复,退出该作用域。
  3. 回到runBlocking主协程:
    • 调用launch { // #1 },将该协程加入调度队列。
    • 执行同步代码println("in the blocking"),输出该行。
    • runBlocking等待所有子协程完成,调度器执行队列中的#1协程,打印coroutine in the blocking。

结果B的执行流程

  1. 第一个coroutineScope:和结果A完全一致,输出相同内容。
  2. 回到runBlocking主协程:
    • 调用launch { // #1 },将该协程加入调度队列。
  3. 第二个coroutineScope:
    • 先执行同步代码println("in the coroutineScope 2"),输出该行。
    • 调用launch,将该协程任务加入调度队列(此时队列中已有#1的协程任务)。
    • coroutineScope挂起等待子协程完成,调度器按队列顺序处理任务:
      • 先执行队列中的#1协程,打印coroutine in the blocking
      • 再执行第二个coroutineScope内的launch协程,依次输出coroutine in the coroutineScope 2和coroutineScope inside the coroutineScope2 coroutine
    • 子协程全部完成,coroutineScope恢复,退出该作用域。
  4. 回到runBlocking主协程:执行同步代码println("in the blocking"),输出该行。

关键结论

  • launch的作用是将协程任务加入调度队列,不会立即执行,具体执行时机由调度器决定。
  • coroutineScope会挂起当前协程,直到所有子协程完成,此时调度器会处理队列中等待的所有协程任务。
  • 单线程调度器下,协程任务严格按加入队列的先后顺序执行,这就是调整launch位置导致输出顺序变化的根本原因。

内容的提问来源于stack exchange,提问作者Steven shih

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 04:13:13