Skip to content

Latest commit

 

History

History
31 lines (17 loc) · 2.51 KB

coroutine.org

File metadata and controls

31 lines (17 loc) · 2.51 KB

coroutine

Tag
Asynchronous programming

协程 coroutine 重点在于 cooperative,协作式,相对应的是 preemptive,抢占式,最经典的实现既 Thread,线程。

这两者都是 multitasking 多任务的机制。

协作式就是各个任务之间相互合作,程序主动在需要等待的时候让出控制权,体现在代码里就是 yeild/await 等机制,golang 则是由编译器隐式插入 yield 点。

而抢占式则是各个程序不协作,相互争抢,由外部调度器决定运行哪个。

前者的优点在于因为是程序自己协作,自然知道挂起/恢复时需要哪些信息,而 OS 线程调度器不知道这些,就得把整个 call stack/ register 的状态都存下来以后才能恢复。这就是协程性能好、更轻量的原因,只需要保存必须的状态。

抢占式的优点在于不需要用户代码关心和处理协作的细节,用户代码更简单且责任少。操作系统如果用协作式的多任务,那一个程序不让出控制权就能卡死整个系统,这也是通用操作系统实现线程的原因。而嵌入式操作系统等用户态可控的环境下,则可以实现协程作为多任务机制。

stackless and stackfull 是协程实现的方式,前者使用类似 stack 的结构保存状态,优点是编写时更接近传统线程,aka 绿色线程。后者则是生成状态机,只保存确实需要的状态,性能最好。

异步是一种调用机制,指调用函数立即返回而不是完成后返回,完成后通过某种方式通知调用方再获取结果。回调和某些语言的 async/await 语法就是为了表达这个过程。

异步 IO 是指通过异步的方式提供 IO 接口,操作系统提供 epoll/io_uring/IOCP 等接口,上层应用 /运行时再封装,常常配和协程、async/await 语法等结合起来以简化使用。

说异步/协程提升性能主要指因为使用了异步 IO 接口,线程不会被阻塞,所以只需要少量线程而不是大量线程等待,少量线程内部再调度协程等待 IO。因为协程更轻量,所以高并发场景下开销小,自然性能就好了。

Promise/Future 等是对异步过程的封装对象,和协程是相关但不同的两个概念。

goroutine 之所以叫 goroutine 而不是 coroutine 就是因为 goroutine 不是完全协作式的,也存在抢占式调度。