go协程的实现方式

**题目来源:**好未来、字节跳动

答案1 :

协程介绍

协程并不是Go发明的概念,支持协程的编程语言有很多,比如Python、Perl等,但没有哪个语言能像Go一样把协程支持的如此优雅,Go在语言层面直接提供对协程的支持称为goroutine。

GMP模型

Go协程调度模型中包含三个关键实体,machine(M)、processor(P)、goroutine(G)

  1. M 工作线程,由操作系统调度
  2. P 处理器,包含运行Go代码的必要资源,也有调度goroutine的能力
  3. G 协程,每个go关键字都会创建一个协程

M必须持有P才可以执行代码,跟系统中的其他线程一样,M也会被系统调用阻塞。P的个数在启动程序时决定,默认情况下等同于CPU的核数,可以使用环境变量GOMAXPROCS或在程序中使用runtime.GOMAXPROCS()方法指定P的个数。

M的个数通常稍大于P的个数,因为除了运行Go代码,runtime包还有其他内置任务需要处理。

image-20220407083925327

上图包含两个工作线程M,每个M持有一个处理器P,并且每个M中有一个协程G在运行。灰色背景的协程正在等待被调度,它们位于被称为runqueues的队列中。每个处理器P中拥有一个runqueues队列,此外还有一个全局的runqueues队列,由多个处理器共享。

开启协程

go语言中通过关键字go开启协程

go func()

匿名协程函数

go func() {}()