协程
协程 : 挂起和恢复 协程 : 程序自己去处理挂起和恢复,是一种协作式调度 线程 : 是操作系统调度,线程之间是抢占式调度
协程:栈的有无 有栈协程:有自己的调用栈,可以在任务函数调用层级去挂起,转移调度权 无栈协程:没有自己的调用栈,通过状态机或者闭包等来实现挂起,能在顶层函数或特定位置暂停和恢复
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
,
- 创建SafeContinuation并传入continuation.intercepted()也就是上文中的ActualContinutaion,
- 执行 block(safe),
- 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
- 确保协程的恢复是线程安全的
- 防止协程被多次恢复
构造函数接收一个Continuation
对象和一个状态值CoroutineSingletons
上述SafeContinuation 2种使用分析:
-
创建SafeContinuation设置result为COROUTINE_SUSPENDED
val safe = SafeContinuation(continuation,COROUTINE_SUSPENDED) safe.resume()
resume():cur = COROUTINE_SUSPENDED,cas 尝试把result修改成RESUMED, 如果修改成功执行continuation.resume()执行invokeSuspend() -
使用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()
}