首先看一个例子:
日志如下:
和withContext的区别是launch后面的代码无需等到async执行完才执行。
字节码如下:
launch部分启动的协程的invokeSuspend逻辑里面,只有label0的逻辑,和withContext不同的是会有挂起部分的判断,所以是同步执行的。
async的异步执行:
日志如下:
可以看到async2是先执行的,因为它没有进行delay,等到两个async执行完了后,才会执行launch里面的代码。
字节码如下:
编译后的代码:
label=0的时候,通过async启动了两个协程,我们这里叫async1和async2,并且在里面通过await挂起了launch启动的协程。
分析:async1调用await后,由于状态是COROUTINE_SUSPENDED,所以第一次invokeSuspend方法结束,此时label=1。等到await逻辑执行完后,又会第二次执行invokeSuspend方法,此时由于lable=1,会执行async2的await方法,此时返回COROUTINE_SUSPENDED,所以invokeSuspend第二次结束,此时label=2。等到async2的await执行完后,第三次执行invokeSuspend方法,由于此时label=2,所以此时切回到自己的线程,执行launch部分的代码逻辑。
总结: async的同步执行是因为没有挂起SuspendLambda的invokeSuspend方法,所以父协程不会挂起,而await方法是挂起函数,默认是返回COROUTINE_SUSPENDED,所以父协程挂起,当子协程逻辑执行完后,会回调父协程的invokeSuspend,当再次执行invokeSuspend的时候,label值发生了变化,因此会执行launch部分的逻辑。