Day5:深入认识 Coroutine

这几天我们把 Coroutine 神秘的面纱好像掀开了一点,知道他是用来解决非同步程序的问题,也我们知道四个 Coroutine 的特点。Coroutine 的轮廓渐渐清晰,本篇文章将继续带你认识 Coroutine。

Coroutine 的定义

Coroutines 是由 cooperation 加上 routine 所组合而成的复合字, cooperation 指共同合作,这里的 routine 意指 function、method,意思是协同处理多个程序(协程)。

Routine(n.) - a sequence of computer instructions for performing a particular task - Merriam-webster

Coroutine

在维基百科是这样说的

Coroutines are computer program components that generalize subroutines for non-preemptive multitasking, by allowing execution to be suspended and resumed.

Coroutines 它是在语言层面上实作的,是属於非抢占式多工 aka 协同式多工。允许计算能够被暂停以及恢复。

Coroutine 被拿来与执行绪做比较,那麽它们两个到底有什麽不同呢?

抢占式多工 VS 协同式多工

首先,我们知道每一个应用程序 (Application) 有一个程序 (Process) 以及一个执行绪 (Thread)。程序有一块独立的记忆体用来把自己应用程序所需的资源与其他应用程序的资源隔离开来,并且依照需要建立执行绪来执行任务。

虽然每一个程序可以建立一个或多个执行绪,但是它们与其他程序所共同分享的是 CPU 的使用时间,系统会根据执行绪的优先权来分配 CPU 时间给执行绪来使用,也就是说,只要有一个优先权较高的任务准备好,就可以中断当下优先权较低的任务。这种由系统根据执行绪的优先权来分配 CPU 时间的多工方式称作抢占式多工(Preemptive multitasking)。

Coroutine 是一种协作式多工 (Cooperative multitasking),相较於抢占式多工 ,协作式多工要求每一个运行中的程序,定时放弃自己的执行权利,告知作业系统可让下一个程序执行。也就是说协程的调度是由协程自行控制,而不是由系统来决定,毕竟在系统的角度下根本不知道有 Coroutine 的存在。

suspend / resume

每一个程序有各自的记忆体,在程序底下的每一个执行绪共用这块记忆体,但是每一个执行绪都有各自的呼叫栈(call stack),这个堆叠纪录所有执行的函式以及变数,所以在执行绪中可以透过 Reference 取得相同的物件,在使用多执行绪的时候,必须要考虑资料的共用,不正确的使用,可能会造成错误发生。

在多执行绪的情况下,在不同的执行绪切换时,需要将目前程序的内容记录下来,在之後切换回来的时候就可以依照这个纪录的内容回到原本的位置。

Kotlin 的 coroutine 则是在每一个 suspend 函式里面都隐藏着一个 Continuation 实例 ,Kotlin 的 coroutine 暂停时(suspend),就会把当下的资讯储存在 Continuation 物件中,Continuation 把这些资讯带着走,当 suspend 函式完成之後,便会把利用 Continuation 储存的资讯切回原本的 Coroutine,所以在 coroutine 中,因为只需要一个 Continuation 物件储存上下文资讯,所以消耗的资源相对的比较少。这类的 coroutine 称之为无栈协程(Stackless coroutine)。那什麽是 Continuation 呢?其实就是一个 Callback。

所以 suspend 必须在 coroutine scope 中执行,因为在 coroutine scope 也包含了Continuation。

小结

Kotlin 的 coroutine 是采用协同式多工,协同式多工是让 coroutine 自行决定任务的调度,而在 Kotlin 的 coroutine 是采用 Stackless coroutine 的设计,这麽做的好处就是可以比执行绪更轻便,不过就无法再任意的地方呼叫 suspend 函式,必须要包含在 coroutine scope 中才能,因为 Coroutine scope 隐含着一个 Continuation 来处理 coroutine 的切换。

特别感谢

Kotlin Taiwan User Group
Kotlin 读书会


<<:  参与"在MCU 上全面建构AI能力" 9/10 心得

>>:  10.需要克服系统差异的大小事 - 变更单

【Docker 攻略】MySQL 安装篇 | 安装资料库 好快的说 !

说明 以下为「 Docker 安装 MySQL 」影片中,使用到的文件内容。 除了安装步骤还会介绍...

[访谈] APCS x 竞程沙漠 Howard

今天邀请到同系同级的 Howard 来分享他在高中学习程序的经历和对於 APCS 的想法~ 程序学习...

【Day 19】Shellcode 与他的快乐夥伴 (下) - Shellcode Loader

环境 Windows 10 21H1 Visual Studio 2019 前情提要 在上一篇【Da...

JS 15 - this 关键字

大家好! 要写到今天也真是不容易呢!明天就要从 50% 开始了! 我们进入今天的主题吧! 严谨模式 ...

EP 03 - Hash ID 计算

Youtube 频道:https://www.youtube.com/c/kaochenlong ...