kotlin 协程创建启动 源码初探(一)

协程

协程 : 挂起和恢复 协程 : 程序自己去处理挂起和恢复,是一种协作式调度 线程 : 是操作系统调度,线程之间是抢占式调度

协程:栈的有无 有栈协程:有自己的调用栈,可以在任务函数调用层级去挂起,转移调度权 无栈协程:没有自己的调用栈,通过状态机或者闭包等来实现挂起,能在顶层函数或特定位置暂停和恢复

kotlin 协程一般认为是一种无栈协程。它通过 suspend 函数和状态机实现挂起和恢复。

无栈协程的优点是轻量级、高性能,但限制是只能在 suspend 函数中挂起。

kotlin 协程一般是非对称协程,协程之间存在父子关系,只在主从之间切换,

创建并启动协程

createCoroutine() startCoroutine()是创建和启动协程的基础Api,后续封装的CoroutineScope launch()等都使用了该基础API。

createCoroutine()和startCoroutine() 基本一致,createCoroutine()只是需要手动resume()开启协程

createCoroutine

kotlin 复制代码
public fun <T> (suspend () -> T).createCoroutine(
    completion: Continuation<T>
): Continuation<Unit> =
    SafeContinuation(createCoroutineUnintercepted(completion).intercepted(), COROUTINE_SUSPENDED)

startCoroutine

kotlin 复制代码
public fun <T> (suspend () -> T).startCoroutine(
    completion: Continuation<T>
) {
    createCoroutineUnintercepted(completion).intercepted().resume(Unit)
}
kotlin 复制代码
fun coroutine1_test1() = runBlocking {
    //接收响应的Continuation
    val responseContinuation = object : Continuation<String> {
        override val context: CoroutineContext
            get() = EmptyCoroutineContext

        override fun resumeWith(result: Result<String>) {
            println("coroutine 结果:" + result.getOrNull().toString())
        }

    }
    val coroutine = suspend {
        getName()
    }.createCoroutine(responseContinuation)
    println("coroutine 启动")
    coroutine.resume(Unit)
    delay(100)
}

suspend fun getName() = suspendCoroutine {
    thread {
        it.resume("我是suspend:getName()")
    }
}

流程图

kotlin Bytecode转换

java 复制代码
public final class Coroutine1 {
   public final void coroutine1_test1() {
      <undefinedtype> responseContinuation = new Continuation() {
         public CoroutineContext getContext() {
            return (CoroutineContext)EmptyCoroutineContext.INSTANCE;
         }

         public void resumeWith(Object result) {
            String var2 = "coroutine 结果:" + (String)(Result.isFailure-impl(result) ? null : result);
            System.out.println(var2);
         }
       };
        Continuation coroutine = ContinuationKt.createCoroutine(
        new Coroutine1$coroutine1_test1$coroutine$1(), responseContinuation);
        String var3 = "coroutine 启动";
        System.out.println(var3);
        Result.Companion var10001 = Result.Companion;
        coroutine.resumeWith(Result.constructor-impl(Unit.INSTANCE));
    }
       
 class Coroutine1$coroutine1_test1$coroutine$1 extends SuspendLambda implements Function1<Continuation<? super Unit>, Object>{    
         int label;
         Coroutine1$coroutine1_test1$coroutine$1(Continuation<? super Continuation<? Coroutine1$coroutine1_test1$coroutine$1> continuation){
             super(1,continuation)
         }   
         public final Object invokeSuspend(Object $result) {
            Object var2 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
            Object var10000;
            switch (this.label) {
               case 0:
                  ResultKt.throwOnFailure($result);
                  var10000 = Coroutine1.this;
                  Continuation var10001 = (Continuation)this;
                  this.label = 1;
                  var10000 = (Coroutine1)var10000.getName(var10001);
                  if (var10000 == var2) {
                     return var2;
                  }
                  break;
               case 1:
                  ResultKt.throwOnFailure($result);
                  var10000 = (Coroutine1)$result;
                  break;
               default:
                  throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
            }
            return var10000;
        }
         public final Continuation create(Continuation $completion) {
            return (Continuation)(new Coroutine1$coroutine1_test1$coroutine$1($completion));
         }
         
          public final Object invoke(Continuation p1) {
            return ((<undefinedtype>)this.create(p1)).invokeSuspend(Unit.INSTANCE);
         }

          public Object invoke(Object p1) {
            return this.invoke((Continuation)p1);
         }
      }
  
       @Nullable
       public final Object getName(@NotNull Continuation $completion) {
          SafeContinuation var3 = new SafeContinuation(IntrinsicsKt.intercepted($completion));
          final Continuation it = (Continuation)var3;
          int var5 = 0;
          ThreadsKt.thread$default(false, false, (ClassLoader)null, (String)null, 0, new Function0() {
             public final void invoke() {
                Result.Companion var10001 = Result.Companion;
                it.resumeWith(Result.constructor-impl("我是suspend:getName()"));
             }
             public Object invoke() {
                this.invoke();
                return Unit.INSTANCE;
             }
          }, 31, (Object)null);
          Object var10000 = var3.getOrThrow();
          if (var10000 == IntrinsicsKt.getCOROUTINE_SUSPENDED()) {
             DebugProbesKt.probeCoroutineSuspended($completion);
          }

          return var10000;
       }
}

createCoroutine() 创建协程

kotlin compiler 会把suspend{}协程体(挂起函数)编译成SuspendLambda通过createCoroutine()创建出一个SafeContinuation,SafeContinuation构造函数接收一个Continuation对象和一个状态值CoroutineSingletons并返回,最终createCoroutine()会接收一个Continuation对象和返回一个Continuation对象。

这里的(suspend () -> T)就是SuspendLambda通过源码可知(下面会详细给出)通过createCoroutineUnintercepted(completion).intercepted() 一个Continuation,可能是SuspendLambda,也可能是DispathedContinuation(如果设置了Continuation的Context[ContinuationInterceptor])。

kotlin 复制代码
public fun <T> (suspend () -> T).createCoroutine(
    //completion = responseContinuation
    completion: Continuation<T>
): Continuation<Unit> =
    SafeContinuation(createCoroutineUnintercepted(completion).intercepted(), COROUTINE_SUSPENDED)

createCoroutineUnintercepted()

suspend{}协程体会编译成内部类SuspendLambda,通过BaseContinuationImpl.create()创建出Continuation对象Coroutine1$coroutine1_test1$coroutine$1

Coroutine1$coroutine1_test1$coroutine$1

下文使用 ActualContinutaion 代替

kotlin 复制代码
@SinceKotlin("1.3")
public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
    completion: Continuation<T>
): Continuation<Unit> {
    val probeCompletion = probeCoroutineCreated(completion)
    return if (this is BaseContinuationImpl)
        create(probeCompletion)
    else
        createCoroutineFromSuspendFunction(probeCompletion) {
            (this as Function1<Continuation<T>, Any?>).invoke(it)
        }
}

ContinuationImpl.intercepted()

上文context = EmptyCoroutineContext,所以context[ContinuationInterceptor] = null, intercepted = this = ContinuationImpl, 如果context = Dispathers.Main, context[ContinuationInterceptor] = HandlerContext.intercepted() ,intercepted =DispathedContinutaion(HandlerContext,ContinuationImpl)

kotlin 复制代码
ContinuationImpl 方法
public fun intercepted(): Continuation<Any?> =
    intercepted
        ?: (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this)
            .also { intercepted = it }
            
Continuation扩展函数

public actual fun <T> Continuation<T>.intercepted(): Continuation<T> =
    (this as? ContinuationImpl)?.intercepted() ?: this

CoroutineDispather

kotlin 复制代码
public final override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
    DispatchedContinuation(this, continuation)

coroutine.resume(Unit)启动协程

createCoroutine可知 coroutine = SafeContinuation(ActualContinutaion(),COROUTINE_SUSPENDED) .resume(Unit) -> resumeWith() 把result修改成RESUMED状态,并执行delegate.resumeWith(result),这里的delegate = ActualContinutaion。 coroutine.resume(Unit)最终执行ActualContinutaion.resumeWith() 执行BaseContinuationImpl.resumeWith()-> invokeSuspend() 这就来到了编译生成的ActualContinutaion的invokeSuspend函数

第一次执行invokeSuspend:

初始lable = 0 条件:首先设置下次执行的条件lable = 1 ,执行协程体里的方法 getName(), safe.getOrThrow() == COROUTINE_SUSPENDED表示协程挂起状态,在BaseContimuationImpl的resumeWith()中,invokeSuspend(param) = COROUTINE_SUSPENDED协程挂起,等待恢复。 在block(safe)-> safe.resume()->delegate.resume("AA")->协程恢复。

第二次执行invokeSuspend:

invokeSuspend(param) = "AA",此时label = 1 返回"AA", 后续BaseContimuationImpl的resumeWith()中,判断invokeSuspend(param)返回值!=COROUTINE_SUSPENDED,继续执行代码,判断completion是否是BaseContimuationImpl,上述可知completion = responseContinuation(Continuation对象), 执行 responseContinuation.resumeWith("AA") 协程执行完毕

suspendCoroutine

suspendCoroutineUninterceptedOrReturn获取当前协程作用域里的Continuation,

  1. 创建SafeContinuation并传入continuation.intercepted()也就是上文中的ActualContinutaion,
  2. 执行 block(safe),
  3. safe.getOrThrow()获取返回值
kotlin 复制代码
public suspend inline fun <T> suspendCoroutine(crossinline block: (Continuation<T>) -> Unit): T {
    ///  
    return suspendCoroutineUninterceptedOrReturn { c: Continuation<T> ->
        val safe = SafeContinuation(c.intercepted())
        block(safe)
        safe.getOrThrow()
    }
}

SafeContinuation

  1. 确保协程的恢复是线程安全的
  2. 防止协程被多次恢复

构造函数接收一个Continuation对象和一个状态值CoroutineSingletons 上述SafeContinuation 2种使用分析:

  1. 创建SafeContinuation设置result为COROUTINE_SUSPENDED val safe = SafeContinuation(continuation,COROUTINE_SUSPENDED) safe.resume() resume():cur = COROUTINE_SUSPENDED,cas 尝试把result修改成RESUMED, 如果修改成功执行continuation.resume()执行invokeSuspend()

  2. 使用UNDECIDED默认值

ini 复制代码
//创建SafeContinuation,result初始状态为UNDECIDED,
val safe = SafeContinuation(continuation)
//执行block方法,比如耗时操作等,拿到数据执行safe.resumeWith("AA"),尝试修改result="AA",成功执行 continuation.resumeWith("AA")协程恢复。
block(safe)
//如果初始UNDECIDED,为尝试修改result = COROUTINE_SUSPENDED,invokeSuspend()= COROUTINE_SUSPENDED,协程挂起,等待block中的方法执行完毕,恢复协程。,
safe.getOrThrow() 
  • UNDECIDED 默认值
  • RESUMED 协程运行状态,防止协程重复恢复(只能恢复一次)
  • COROUTINE_SUSPENDED 协程挂起状态
kotlin 复制代码
internal actual class SafeContinuation<in T>
internal actual constructor(
    private val delegate: Continuation<T>,
    initialResult: Any?
) : Continuation<T>, CoroutineStackFrame {
    @PublishedApi
    //默认状态UNDECIDED
    internal actual constructor(delegate: Continuation<T>) : this(delegate, UNDECIDED)

    public actual override val context: CoroutineContext
        get() = delegate.context

    @Volatile
    private var result: Any? = initialResult

    private companion object {
        @Suppress("UNCHECKED_CAST")
        //原子操作
        private val RESULT = AtomicReferenceFieldUpdater.newUpdater<SafeContinuation<*>, Any?>(
            SafeContinuation::class.java, Any::class.java as Class<Any?>, "result"
        )
    }

    public actual override fun resumeWith(result: Result<T>) {
        while (true) { 
            val cur = this.result 
            when {
                cur === UNDECIDED -> if (RESULT.compareAndSet(this, UNDECIDED, result.value)) return
                cur === COROUTINE_SUSPENDED -> if (RESULT.compareAndSet(this, COROUTINE_SUSPENDED, RESUMED)) {
                    delegate.resumeWith(result)
                    return
                }
                else -> throw IllegalStateException("Already resumed")
            }
        }
    }

    @PublishedApi
    internal actual fun getOrThrow(): Any? {
        var result = this.result // atomic read
        if (result === UNDECIDED) {
            if (RESULT.compareAndSet(this, UNDECIDED, COROUTINE_SUSPENDED)) return COROUTINE_SUSPENDED
            result = this.result // reread volatile var
        }
        return when {
            result === RESUMED -> COROUTINE_SUSPENDED // already called continuation, indicate COROUTINE_SUSPENDED upstream
            result is Result.Failure -> throw result.exception
            else -> result // either COROUTINE_SUSPENDED or data
        }
    }
}

SuspendLambda

kotlin 复制代码
internal abstract class SuspendLambda(
    public override val arity: Int,
    completion: Continuation<Any?>?
) : ContinuationImpl(completion), FunctionBase<Any?>, SuspendFunction {
    constructor(arity: Int) : this(arity, null)

    public override fun toString(): String =
        if (completion == null)
            Reflection.renderLambdaToString(this) // this is lambda
        else
            super.toString() // this is continuation
}

suspend{}协程体通过kotlin compiler编译器,编译成 SuspendLambda

final class com.junit.test.KComplier$test$1 extends kotlin.coroutines.jvm.internal.SuspendLambda implements kotlin.jvm.functions.Function1<kotlin.coroutines.Continuation<? super kotlin.Unit>, java.lang.Object>

ContinuationImpl

kotlin 复制代码
internal abstract class ContinuationImpl(
    completion: Continuation<Any?>?,
    private val _context: CoroutineContext?
) : BaseContinuationImpl(completion) {
    constructor(completion: Continuation<Any?>?) : this(completion, completion?.context)

    public override val context: CoroutineContext
        get() = _context!!

    @Transient
    private var intercepted: Continuation<Any?>? = null
    //获取协程拦截器(调度)ContinuationInterceptor
    //比如Dispatchers.Main/Dispatchers.IO,切换线程使用
    public fun intercepted(): Continuation<Any?> =
        intercepted
            ?: (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this)
                .also { intercepted = it }

    protected override fun releaseIntercepted() {
        val intercepted = intercepted
        if (intercepted != null && intercepted !== this) {
            context[ContinuationInterceptor]!!.releaseInterceptedContinuation(intercepted)
        }
        this.intercepted = CompletedContinuation // just in case
    }
}

BaseContinuationImpl

kotlin 复制代码
internal abstract class BaseContinuationImpl(
    public val completion: Continuation<Any?>?
) : Continuation<Any?>, CoroutineStackFrame, Serializable {
    
    public final override fun resumeWith(result: Result<Any?>) {
        var current = this
        var param = result
        while (true) {
            probeCoroutineResumed(current)
            with(current) {
                val completion = completion!!
                val outcome: Result<Any?> =
                    try {
                        
                        val outcome = invokeSuspend(param)
                        //当invokeSuspend()==COROUTINE_SUSPENDED
                        //协程挂起
                        if (outcome === COROUTINE_SUSPENDED) return
                        Result.success(outcome)
                    } catch (exception: Throwable) {
                        Result.failure(exception)
                    }
                releaseIntercepted() 
                //还是BaseContinuationImpl 说明还没有执行完毕,继续循环
                if (completion is BaseContinuationImpl) {
                    current = completion
                    param = outcome
                } else {
                   //执行完毕,completion最后接收数据的Continuation
                    completion.resumeWith(outcome)
                    return
                }
            }
        }
    }

    protected abstract fun invokeSuspend(result: Result<Any?>): Any?

    protected open fun releaseIntercepted() {
        // does nothing here, overridden in ContinuationImpl
    }

    public open fun create(completion: Continuation<*>): Continuation<Unit> {
        throw UnsupportedOperationException("create(Continuation) has not been overridden")
    }
    
    public open fun create(value: Any?, completion: Continuation<*>): Continuation<Unit> {
        throw UnsupportedOperationException("create(Any?;Continuation) has not been overridden")
    }
  
    public override val callerFrame: CoroutineStackFrame?
        get() = completion as? CoroutineStackFrame

    public override fun getStackTraceElement(): StackTraceElement? =
        getStackTraceElementImpl()
}
相关推荐
小白马丶2 分钟前
Jetpack源码解读(一)——Lifecycle
android·android jetpack
&有梦想的咸鱼&19 分钟前
Android Glide 请求构建与管理模块原理深入剖析
android·glide
苏苏码不动了21 分钟前
Android MVC、MVP、MVVM三种架构的介绍和使用。
android·架构·mvc
万里鹏程转瞬至43 分钟前
开源项目介绍:Native-LLM-for-Android
android·深度学习·开源·大模型
QING6183 小时前
Android_BLE 基于Jetpack Bluetooth实现文件传输指南。
android·kotlin·app
_一条咸鱼_4 小时前
Android Glide 的显示与回调模块原理分析
android
_一条咸鱼_4 小时前
Android Glide 图片解码与转换模块原理分析
android
QING6184 小时前
Android_BLE开发——扫描
android·kotlin·app
QING6184 小时前
Android_BLE开发——绑定
android·kotlin·app
顾林海4 小时前
深入理解 Dart 函数:从基础到高阶应用
android·前端·flutter