最近在学习goroutine,记点笔记...
golang中协程目前使用的是GMP模型
GMP描述
- G: goroutine,可以理解为协程
- M:线程,内核线程,goroutine跑在M之上的 ( M的数量在
runtime
/debug
包的SetMaxThreads()
决定。如果当前的M阻塞,就会新建一个新的线程。) - P:调度器,goroutine的队列 (P的数量由
GOMAXPROCS
环境变量,或者runtime
中GOMAXPROCS()
函数决定的。)
注意:M的数量和P的数量没有关系。如果当前的M阻塞,P的goroutine会运行在其他的M上,或者新建一个M。所以可能出现有很多个M,只有1个P的情况。

说明:
- 全局队列:要执行goroutines的队列
- P 本地队列:与全局队列一样,它包含要执行的goroutine;但是这个队列的最大容量是256。当本地队列已满时,会将gorouting的一半发送到全局队列;最后,G创建的Goroutine 将在同一个队列中排队,以确保本地关联
- P 列表:一旦确定GOMAXPROCS的值,所有P的列表都将被创建
- M 正在运行的线程:从P的本地队列获取任务,如果该队列为空,M将从全局队列获取goroutines到P的本地队列,或者从其他P的队列获取goroutines。G在M中运行,当任务完成时,它将继续拉一个新的G
Goroutine调度程序和OS调度程序使用M连接,每个M是一个物理OS线程,OS调度程序调度M运行在一个真正的CPU内核中。
go func()
执行流程:

go func(){}
创建一个新的goroutine
。- G保存在P的本地队列,如果本地队列满了,保存在全局队列。
- G在M上运行,每个M绑定一个P。如果P的本地队列没有G,M会从其他P的本地队列,挥着G的全局队列,窃取G。
- 当M阻塞时,会将M从P解除。把G运行在其他空闲的M或者创建新的M。
- 当M恢复时,会尝试获得一个空闲的P。如果没有P空闲,M会休眠,G会放到全局队列。
Comments | NOTHING