浅谈kotlin的协程

Posted by

Go语言的协程曾经是一大卖点,kotlin在1.1+版本中也实现了协程。不过目前kotlin的协程实现,还是试验性质的,也就是说以后可能会大改。下面谈谈,我对kotlin协程的理解。

第一:什么是协程

kotlin官方文档里描述的还算清楚:

一些 API 启动长时间运行的操作(例如网络 IO、文件 IO、CPU 或 GPU 密集型任务等),并要求调用者阻塞直到它们完成。协程提供了一种避免阻塞线程并用更廉价、更可控的操作替代线程阻塞的方法:协程挂起

协程通过将复杂性放入库来简化异步编程。程序的逻辑可以在协程中顺序地表达,而底层库会为我们解决其异步性。该库可以将用户代码的相关部分包装为回调、订阅相关事件、在不同线程(甚至不同机器!)上调度执行,而代码则保持如同顺序执行一样简单。

许多在其他语言中可用的异步机制可以使用 Kotlin 协程实现为库。这包括源于 C# 和 ECMAScript 的 async/await、源于 Go 的 管道 和 select 以及源于 C# 和 Python 生成器/yield

协程说白一点,实际上就是在线程里,通过异步的方式执行一些请求。比如说网络请求,磁盘IO的请求,CPU或者GPU的请求等。

第二:协程的优势

上面我们谈了什么是协程,接下来我们讲讲协程有什么优势,他的应用场景是什么。如果系统执行请求的压力不大,那么协程的必要性也没那么大。传统的多进程和多线程能搞定的同步请求,没必要用协程。

协程只要是在高并发的场景下,为提高系统并发处理能力而生的。他的资源开销,会比同步多线程更小。

第三:操作系统挂起是什么意思

在解释kotlin协程的概念之前,先要解释下操作系统挂起的概念。这里引用了维基百科的解释:

挂起是指在操作系统进程管理将前台的进程暂停并转入后台的动作。将进程挂起可以让用户在前台执行其他的进程。挂起的进程通常释放除CPU以外已经占有的系统资源,如内存等。

在需要时用户可以恢复进程的运行,将被挂起的进程从后台转入前台,并从暂停处开始继续运行。

第四:kotlin协程的优势和协程解决的问题

这个问题kotlin官方文档是这么解释的:

基本上,协程计算可以被挂起而无需阻塞线程。线程阻塞的代价通常是昂贵的,尤其在高负载时,因为只有相对少量线程实际可用,因此阻塞其中一个会导致一些重要的任务被延迟。

另一方面,协程挂起几乎是无代价的。不需要上下文切换或者 OS 的任何其他干预。最重要的是,挂起可以在很大程度上由用户库控制:作为库的作者,我们可以决定挂起时发生什么并根据需求优化/记日志/截获。

另一个区别是,协程不能在随机的指令中挂起,而只能在所谓的挂起点挂起,这会调用特别标记的函数。

白话解释一下:协程会在执行请求之前,先去检查系统是否有足够的资源来执行请求。当没有足够的资源时,先执行那个简单的没有什么开销的,协程挂起函数。当系统空闲,有资源时,再来执行请求。

这就解决了,多线程并发请求时,最尴尬的线程阻塞的问题。

第五:kotlin挂起的协程干什么去了

kotlin的官方文档稍微写了一下,挂起的协程的机制。实际上就是把协程的任务,所涉及到的变量和方法,保存到一个类中。等系统有资源执行请求后,再去解析这个类,去按照顺序执行方法。

这里有一个概念叫有限状态机,实际上每一个协程的挂起函数,都是一个有限状态机。接下来,再阐述下有限状态机。

第六:kotlin协程的挂起函数实际上是一个有限状态机

这里继续引用维基百科的解释:所谓有限状态机(英语:finite-state machine,缩写:FSM)又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。

状态存储关于过去的信息,就是说:它反映从系统开始到现在时刻的输入变化。转移指示状态变更,并且用必须满足确使转移发生的条件来描述它。动作是在给定时刻要进行的活动的描述。在计算机科学中,有限状态机被广泛用于建模应用行为、硬件电路系统设计、软件工程,编译器、网络协议、和计算与语言的研究。

kotlin协程,本质上还是利用了状态机的特点。kotlin官方文档中描述:

协程的内部机制中,其中的状态对应于挂起调用。刚好在挂起前,下一状态与相关局部变量等一起存储在编译器生成的类的字段中。在恢复该协程时,恢复局部变量并且状态机从刚好挂起之后的状态进行。

挂起的协程可以作为保持其挂起状态与局部变量的对象来存储和传递。这种对象的类型是 Continuation,而这里描述的整个代码转换对应于经典的延续性传递风格(Continuation-passing style)。因此,挂起函数有一个 Continuation 类型的额外参数作为高级选项。

One comment

Leave a Reply

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据