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的ContextContinuationInterceptor)。

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,所以contextContinuationInterceptor = null, intercepted = this = ContinuationImpl, 如果context = Dispathers.Main, contextContinuationInterceptor = 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()
}
相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
ai2work1 天前
ch23 综合复刻:从零做一个最小可用版本(capstone)
kotlin
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
ai2work2 天前
ch21 签名、校验与发版
kotlin
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui