Goroutine的定义:
说到 gmp之前要先了解goroutine,golang在语言级别支持协程,称作goroutine。golang标准库提供的所有系统调用操作(包括所有同步的I/O操作),都会出让CPU给其他Goroutine。这让goroutine的管理不依赖于系统的进程和线程,也不依赖于cpu的核心数量,而是交给golang的运行时同意调度。
GMP是什么:
G: goroutine,用户级的轻量协程,每个goroutine对象中的sched保存着齐上下文信息。
M: machine 内核级线程的封装,数量对应真实的cpu核心数(真正干货的对象)
P: processor. G和M的调度对象,用来调度G和M之间的关系,其数量可以通过GOMAXPROCS()来设置,默认为cpu的核心数
GMP调度流程:
1、每个P有个局部队列,局部队列保存着待执行的goroutine,局部队列满了之后goroutine会放在一个全局队列里面
2、每个P和一个M绑定,M是真正执行P中goroutine的实体,M从绑定的P中的局部队列里获取goroutine来执行
3、当M绑定的P的局部队列为空时,M会从全局队列里获取G来执行。当没有从全局队里里获取到G的时候,会从其他P的局部队列偷取G来执行,这种方式称为work stealing
4、当G因系统调用而阻塞时会阻塞M,此时P会和M解绑,即handoff,并寻找新的空闲的M,如果没有空闲的M就会新建一个M
5、当G因为channel或者network I/O阻塞时,不会阻塞M,M会寻找其他runnalbe的G;当阻塞的G恢复后会重新进入p队列等待执行