在Kotlin协同程序中暂停function是什么意思

我正在阅读Kotlin Coroutine,知道它是基于suspendfunction的。 但suspend是什么意思?

协程或函数被暂停?

从https://kotlinlang.org/docs/reference/coroutines.html

基本上,协程是可以暂停而不阻塞线程的计算

我听到有人经常说“暂停function”。 但是我认为是因为等待函数完成而被暂停的协程? “挂起”通常意味着“停止运行”,在这种情况下,协程是空闲的。

🤔我们应该说协程暂停了吗?

哪个协程暂停?

从https://kotlinlang.org/docs/reference/coroutines.html

为了继续这个比喻,await()可以是一个挂起函数(因此也可以从async {}块中调用)暂停一个协程,直到某个计算完成并返回结果:

 async { // Here I call it the outer async coroutine ... // Here I call computation the inner coroutine val result = computation.await() ... } 

🤔它说“暂停一个协程,直到一些计算完成”,但协程就像一个轻量级的线程。 所以如果协程暂停,那么计算如何完成呢?

我们看到await被调用computation ,所以它可能是async ,返回Deferred ,这意味着它可以启动另一个协程

 fun computation(): Deferred { return async { true } } 

🤔引用说暂停协程 。 是指suspend外部async协程,还是suspend内部computation协程?

suspend是指在外部async协程为内部computation协程完成等候( await )完成时,它(外部async协程)空闲(因此名称暂停)并将线程返回到线程池,并且当子computation协程完成时,它(外部async协程)醒来,从池中取出另一个线程并继续?

我提到这个线程的原因是因为https://kotlinlang.org/docs/tutorials/coroutines-basic-jvm.html

线程在协程正在等待时返回到池中,等待完成后,协程将在池中的空闲线程上恢复

作为一个学习工具,我建议你通过这个代码,它揭示了所有的便利构造,如async的基本机制:

 import kotlinx.coroutines.experimental.Unconfined import kotlinx.coroutines.experimental.launch import kotlin.coroutines.experimental.Continuation import kotlin.coroutines.experimental.suspendCoroutine var continuation: Continuation? = null fun main(args: Array) { launch(Unconfined) { val a = a() println("Result is $a") } 10.downTo(0).forEach { continuation!!.resume(it) } } suspend fun a(): Int { return b() } suspend fun b(): Int { while (true) { val i = suspendCoroutine { cont -> continuation = cont } if (i == 0) { return 0 } } } 

Unconfined协程上下文基本上消除了协程上下文的魔力:你只要开始执行launch块内的代码。 会发生什么如下:

  1. 评估val a = a()
  2. 这链接到b() ,到达suspendCoroutine
  3. 函数b()执行传递给suspendCoroutine的块,然后返回一个特殊的COROUTINE_SUSPENDED值。 这个值通过Kotlin编程模型是不可观测的,但这正是编译的Java方法所做的。
  4. 函数a() ,看到这个返回值,本身也返回它。
  5. launch块执行相同的操作,现在控件在launch调用之后返回到这一行: 10.downTo(0)...

请注意,在这一点上,你有相同的效果,如果launch块内的代码和你的fun main代码并发执行。 这只是发生在一个本地线程上,所以launch块被“暂停”。

现在,在forEach循环代码中,程序读取b()函数编写的continuation ,并以10的值resumesresume()以这种方式实现,就好像suspendCoroutine调用返回的值一样。它被赋值给i并且被检查为0 。 如果它不为零,那么while (true)循环在b()内部继续,再次到达suspendCoroutine ,在这一点你的resume()调用返回,现在你通过forEach()另一个循环步骤。 这继续下去,直到最后你恢复0 ,然后println语句运行,程序完成。

上面的分析应该给你一个重要的直觉,即“暂停协程”意味着将控制返回到最内层的launch调用(或者更一般地说, 协程生成器 )。

协同工作环境的存在使得这个推理不太清晰,因为他们中的大多数立即提交你的代码到另一个线程。 在这种情况下,上述故事发生在另一个线程中,并且协程上下文也管理continuation对象,以便在返回值可用时继续它。