Coroutine (协程)
协程是计算机程序的一类组件,允许执行被挂起与被恢复。咱们常见的异常处理、事件循环、迭代器等也更适合使用协程实现。协程是在语言层的实现,所以协程的切换不需要操作系统保存状态,所以它不是 OS-managed。 Coroutine 也被分为 :
stackful
每个协程都有独立的运行栈,当被挂起时,它的调用栈会被保存到内存中,等待协程被重新唤醒时再恢复调用栈。
Pros: 这种协程实现的较为完整, 可以被嵌套,循环。 Cons: 由于会分配独立的调用栈,有栈协程会占用较多的内存空间,切换速度相对较慢。
stackless
与有栈协程相对的,无栈协程不需要自己的调用栈,而是共享一个调用栈。当协程需要挂起时,它的状态会被保存到内存中,而不是整个调用栈。当协程被重新唤醒时,它的状态会被恢复到调用栈中。
Pros: 由于不需要维护独立的自己的栈。所以切换速度相对较快,且占用的内存也较少。 Cons: 不完整功能较弱,无法嵌套,循环,和异步函数进行控制流调度。但async/await则是个例外。
简单聊聊javascript开发者最为熟悉的 async/await模型。
async/await 模型也属于coroutine的一种,是一种stackless协程。但我们会发现async/await却可以被嵌套和循环。这是因为async/await 实现了基于stackless coroutine的完整coroutine,在特性上十分接近有栈协程。
在JavaScript的相关文章中经常会看到这样的定义, async/await是在Generator和Promise基础上构建的一种语法糖。在JavaScript中,协程通常使用生成器函数来实现。
我们会发现async/await并不会涉及原生线程的内容,所以它是一种语言特性,它通常是在编译器的语法分析阶段产生(也就是AST构建阶段)。而 JavaScript、Rust 等等语言一开始就提供了这种特性,但并没有提供Async Runtime,于是出现了JavaScript的Nodejs,Rust的Tokio, 等等。
Fiber
Fiber 一般由操作系统管理,但也可以在没有操作系统支持的情况下实现。Fiber也被称为stackful coroutines (wiki: sometimes called stackful coroutines or user mode cooperatively scheduled threads),但是这并不是说fiber和coroutine是一样的 ,fiber本质上是一个调度实体,在fiber上可以执行普通函数,或协程;而coroutine本质上是一个函数,取决于实现,其可能是stackful或者stackless。
Green Thread (绿色线程)
绿色线程是一种由Runtime或VM调度,而不是由本地底层操作系统度的线程。绿色线程并不依赖底层的系统功能,模拟实现了多线程的运行,这种线程的管理调配发生在Userspace而不是Kernelspace,所以可以在没有原生线程支持的环境中运行。
与coroutine比较
绿色线程保存完整的上下文,大部分由虚拟机实现,开销比较大协程大多数实现中不保存完整的上下文。
ProtoThreads
Wiki定义:Protothreads可用于实现叫做协作式多任务的非抢占形式的并发计算,故而在一个线程yield(让步)给另一个线程的时候不会招致上下文切换。为了在一个protothread内达成yield,在线程函数内利用了达夫设备并在其switch语句内使用一个函数外部的变量。这允许在另一次函数调用时跳转(恢复)到上次的yield的地方。为了阻塞线程,这些yield要通过等待条件来守卫,使得后续的对同样这个函数的调用仍然yield,直到这个条件表达式是为真值为止。
Actors (演员模型)
来自chatgpt的定义: actor是一种基于消息传递的并发模型,它把并发实体(actor)看作是一个个独立的个体,每个actor都有自己的状态和行为,它们之间通过异步的消息来通信和协作。actor不会共享状态,也不会阻塞或等待其他actor的回复,这样可以避免死锁和竞态条件等问题。actor模型可以很好地支持分布式系统,因为消息传递是分布式系统的基础。
Web Worker与Actor模型有一些相似之处,它们都使用消息传递来实现线程之间的通信。但是,它们的实现方式略有不同。在Web Worker中,消息传递是基于JavaScript对象的,它通过postMessage()和onmessage事件来实现。而在Actor模型中,消息传递是基于Actor之间的交互,每个Actor都有一个接收消息的邮箱,它们通过邮箱来接收和发送消息。
Web Worker更像是一种“轻量级”的Actor模型,它只提供了消息传递的基本机制,而没有提供像邮箱和Actor之间的交互等高级功能。
其余
- CSP golang开发者可能较为熟悉。
p.s. 以上并发模型可能因实现方式和编程语言而有所不同,此文仅小记。