引子

这个话题起源于今天在某不存在的聊天软件 Telegram 上有位网友提问了一个问题:“ Green ThreadCoroutine 的区别在哪里?”

因为我的擅长语言是 C++ 的原因,一开始连 Green Thread 是什么都不知道。

查询了许多资料(中文网站)后发现许多搜索结果描述 Green ThreadCoroutine 是同一种东西——我几乎相信了,如果不是维基给了两个不同的页面介绍这两者的话。

更换英文搜索后我得到了更详细的资料(在文末列出),证明 Green ThreadCoroutine 是不同的东西。我把这些记录在本文,希望能对读者有所启发。

正文

首先来介绍一下 Green ThreadCoroutine

绿色线程 Green Thread

绿色线程 Green Thread 的概念是相对于操作系统线程(原生线程 native thread)提出的,因为绿色线程并不是操作系统级别的概念。
绿色线程实际上是语言级别实现的线程。通常由 VM 来进行控制其资源分配和调度。因此,当一个绿色线程使用系统调用被阻塞时,操作系统并不会帮助调度其他线程,因此会导致该进程内所有线程(绿色线程)被阻塞。
第一个提出绿色线程概念的是早期 Java 的线程库,因为本身与系统无关的特性,可以在没有原生线程支持的环境中运行。

协程 Coroutine

协程也是在用户层(语言级别)进行实现的,是一种比线程更小的执行单元。协程自带 CPU 上下文,因此可以在任意时刻切换到别的协程。和线程比起来,协程的切换不需要操作系统进行保存和恢复CPU 上下文,自己的缓存数据等,因为所有的协程都存在于同一个线程之中,所以协程的切换只有单纯的 CPU 上下文切换,开销很小。
协程也有一个调度器,但是是被动调度的,也就是说,只有当前运行的协程主动的让出 CPU,调度器才会从协程池中调用下一个协程。这也是协程和上边几种最大的区别:协程的调度方式是合作式(Cooperative),也可以叫做非抢占式(Non-Preemptive);而上边三种都是抢占式调度(Preemptive)。

两者的比较

这里来列出 绿色线程协程 的共同点:

  • 都是用户态操作。
  • 都会被 I/O 操作堵塞当前 原生线程 native thread
  • 开销都比较小(大概)

之后自然是列出不同点:

  • 上下文不同
    • 协程大多数实现中不保存完整的上下文,比如我知道的腾讯 C++ 协程库 libco 就选择了丢弃浮点运算的操作(他们可能想着服务器环境不怎么需要浮点运算)并且内联汇编加快上下文切换速度导致只能支持 X86(离题)。所以协程的开销尤其小。
    • 绿色线程保存完整的上下文,一般都由虚拟机实现(大部分),开销比较大。
  • 并行性不同
    • 一个原生线程开出多个协程,这些协程彼此并不能并行,只能并发。并发与并行的简单解释
    • 绿色线程这边比较复杂。要分情况讨论:
      • 在早期 JAVA 使用绿色线程的时候,所有的绿色线程都是属于同一个线程的,并没有利用到 CPU 的多核处理程序。这时候绿色线程也是只能并发不能并行的。
      • 在现在的绿色线程实现中,绿色线程会被匹配到一个原生线程池,从原生线程池中获取原生线程来执行绿色线程。有时候是 1 个原生线程执行 m 个绿色线程——这时候和早期没什么区别;有时候是 n 个原生线程执行 m 个绿色线程——这时候的绿色线程就获得了并行能力。

由最重要的并行性比较中可以看出,绿色线程和协程差别还是挺大的。在目前流行的编程语言中,有的语言选择了协程,有的语言选择了绿色线程,我用的 C++ 似乎没有绿色线程可以用的样子

参考资料

正经的参考资料:

  1. Processes, threads, green threads, protothreads, fibers, coroutines: what's the difference?
  2. 协程 - 维基百科
  3. 绿色线程 - 维基百科
  4. 协程?还有纤程、绿色线程、线程、进程??
  5. Java的Green threads是Coroutine吗?

说绿色线程等于协程的文章(找不到原始出处了):

  1. 协程,纤程(Fiber),或者绿色线程(GreenThread)
文章目录