一文看懂Go语言协程的设计与原理

首发于微信公众号:【码农在新加坡】,欢迎关注。

个人博客网站:一文看懂Go语言协程的设计与原理

背景

Go语言最大的特色就是从语言层面支持并发(Goroutine),Goroutine是Go中最基本的执行单元。事实上每一个Go程序至少有一个Goroutine:main Goroutine。Go 程序从 main 包的 main() 函数开始,在程序启动时,Go 程序就会为 main() 函数创建一个默认的 goroutine。

为了了解Go语言协程的设计,我们从历史设计出发,来看看最终Goroutine怎么一步一步到现在的设计的。

单进程时代

早期的操作系统每个程序就是一个进程,操作系统在一段时间只能运行一个进程,直到这个进程运行完,才能运行下一个进程,这个时期可以成为单进程时代——串行时代。

如图:进程之间串行执行,A、B、C 三个进程按顺序执行。

单进程时代的两个问题:

  1. 单一执行流程、计算机只能一个任务一个任务的处理。
  2. 进程阻塞所带来的CPU浪费时间是不可避免的(如进程A阻塞了,然后CPU是单进程没有任何的切换能力,但是需要等待进程A结束后才能执行下个进程)

遇到这种问题,我们怎么才能充分利用CPU呢?

多进程时代

后来操作系统就具有了最早的并发能力:多进程并发,当一个进程阻塞的时候,切换到另外等待执行的进程,这样就能尽量把CPU利用起来,CPU就不浪费了。

在多进程时代,有了时间片的概念,进程按照调度算法分时间片在 CPU 上执行,A、B、C 三个进程按照时间片并发执行。(调度算法)
一文看懂Go语言协程的设计与原理_第1张图片

这样做有两个优点:

  1. 对于单个核可以并发执行多个进程,应用场景更加丰富,
  2. 当某个进程 IO 阻塞时,也能保证 CPU 的利用率。

但是随着时代的发展,CPU 通过进程来进行调度的缺点也越发的明显。

进程切换需要:

  1. 切换页目录以使用新的地址空间
  2. 切换内核栈和硬件上下文

因为进程拥有太多资源,在创建、切换和销毁的时

你可能感兴趣的:(golang,后端,开发语言,go)