首页 > 解决方案 > kotlin 协程是如何在底层实现的?

问题描述

Kotlin 协程是该语言的关键特性之一。我很好奇他们是如何实现的。所以我写了这个 kotlin 代码片段,

CoroutineScope(Dispatchers.IO).launch {
    someFun(6)  // A suspend fun with single int argument.
}  // Which is converted into a synthetic method with an extra argument of continuation type added at the end.

然后将其编译为字节码,然后将其反编译为 Java(在 Android Studio 中)。我懂了,

BuildersKt.launch$default(CoroutineScopeKt.CoroutineScope((CoroutineContext)Dispatchers.getIO()), (CoroutineContext)null, (CoroutineStart)null, (Function2)(new Function2((Continuation)null) {
   private CoroutineScope p$;
   Object L$0;
   int label;
            
   @Nullable
   public final Object invokeSuspend(@NotNull Object $result) {
      Object var3 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
      CoroutineScope $this$launch;
      switch(this.label) {
      case 0:
         ResultKt.throwOnFailure($result);
         $this$launch = this.p$;
         MainActivity var10000 = MainActivity.this;
         this.L$0 = $this$launch;
         this.label = 1;
         if (var10000.someFun(6, this) == var3) {
            return var3;
         }
         break;
      case 1:
         $this$launch = (CoroutineScope)this.L$0;
         ResultKt.throwOnFailure($result);
         break;
      default:
         throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
      }
            
      return Unit.INSTANCE;
   }
            
   @NotNull
   public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
      Intrinsics.checkNotNullParameter(completion, "completion");
      Function2 var3 = new <anonymous constructor>(completion);
      var3.p$ = (CoroutineScope)value;
      return var3;
   }
            
   public final Object invoke(Object var1, Object var2) {
      return ((<undefinedtype>)this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
   }
}), 3, (Object)null);

我理解了这段代码的某些部分。但仍有一些部分没有进入我的脑海。

根据这个invokeSuspend答案,一个挂起函数在每个挂起点被拆分为多个延续,然后通过连续调用从头开始执行。每次invokeSuspend调用 when 时,都会执行相应的 switch case,然后更新lable. 所以下次当invokeSuspend被调用时,它会运行下一个案例。当 <it?> 被调用挂起函数时,它停止调用invokeSuspend并等待恢复调用。一旦它被调用恢复,它再次正常继续。这就是我所知道的。

在第一行,Function2 构造函数为 Continuation 接受一个空对象。但是为什么Function2类只有一个参数构造函数呢?我不知道Function2的实现。我搜索了它的源代码,但没有得到它。如果可能的话,我想要一个指向源代码的链接kotlin.jvm.functions.Function2

在 case0: 的末尾,if (var10000.someFun(6, this) == var3) return var3;实际上是什么意思。

在上一次调用 invokeSuspend 完成后,谁负责调用 invokeSuspend。以及它如何知道最后一个 invokeSuspend 案例何时执行?

3, (Object)null最后一个参数代表什么launch$default

标签: javakotlinkotlin-coroutines

解决方案


推荐阅读