协程?还有纤程、绿色线程、线程、进程??
前两天和同事讨论起 Go 语言的 Goroutine,然后说起了“协程”。这才了解到原来除了进程,线程,还有协程的概念。 晚上回家一查,天啊,还有纤程,绿色线程,直接懵逼了,什么时候冒出来了这么多程?
那么在这里就大概做个总结吧。有进程(process)、线程(thread)、绿色线程(Green Thread)、协程(Coroutine)和纤程(Fiber)。
进程
狭义定义: 进程是正在运行的程序的一个实例。
进程是一个实体,是资源分配的基本单位。每一个进程都有自己的地址空间,一般包括文本区域、数据区域和堆栈。
文本区域存储代码;数据区域存储变量和动态分配的内存;堆栈区域存储着调用的指令和本地变量。
线程
线程是进程中的一个实体,是系统调度的基本单位。被包含在进程当中,是操作系统进行运算调度的最小单位。
一个进程可以有多个线程,这些线程共享该进程中的全部系统资源,比如虚拟地址空间,文件描述符和信号处理等等。但每个线程拥有自己的调用栈,自己的寄存器环境和自己的本地存储。
所以启动一个线程的开销比启动一个进程的开销要小得多。而且多线程之间共享数据更加快捷方便。
绿色线程
绿色线程的概念是相对于操作系统线程(原生线程)提出的,因为绿色线程并不是操作系统级别的概念。
绿色线程实际上是语言级别实现的线程。通常由 VM 来进行控制其资源分配和调度。因此,当一个绿色线程使用系统调用被阻塞时,操作系统并不会帮助调度其他线程,因此会导致该进程内所有线程(绿色线程)被阻塞。
协程
协程也是在用户层(语言级别)进行实现的,是一种比线程更小的执行单元。协程自带 CPU 上下文,因此可以在任意时刻切换到别的协程。和线程比起来,协程的切换不需要操作系统进行保存和恢复CPU 上下文,自己的缓存数据等,因为所有的协程都存在于同一个线程之中,所以协程的切换只有单纯的 CPU 上下文切换,开销很小。
协程也有一个调度器,但是是被动调度的,也就是说,只有当前运行的协程主动的让出 CPU,调度器才会从协程池中调用下一个协程。这也是协程和上边几种最大的区别:协程的调度方式是合作式(Cooperative),也可以叫做非抢占式(Non-Preemptive);而上边三种都是抢占式调度(Preemptive)。
纤程
在能查到的很多网络论坛和博客中,都将纤程和协程当做同一个概念,只是协程是一个概念,而纤程是 Windows 系统对协程的一个具体实现。可以在知乎问答和廖雪峰的博文中看到相关解释。 但是我也在某些文档和博客中看到了其它的观点。 比如 Wiki中解释到:
- 纤程和协程都是合作式调度
- 纤程是操作系统级别的,而协程是语言级别的实现
总结
-
实现级别的不同: 系统级别实现:进程、线程、纤程 用户级别实现:绿色线程、协程
-
调度方式的不同: 抢占式:进程、线程、绿色线程 合作式:纤程、协程
题外话
在研究各种概念的过程中,这次有帮助没有中文页面的一些 Wiki 条目进行了中文翻译,还有挺有意思的,虽然没有什么回报,但是想到自己翻译的内容能为其它人所用,就有一种满足感。难怪那么多人疯狂的投身于各种公益、开源项目。希望自己也能坚持下去,多做一些类似的事情。