Go之GMP模型

8 阅读2分钟
背景

最近参与go语言面试,回想起之前参与的go语言面试,在go基础这一块,经常会被问到GMP,这也是go很牛的一个goroutine调度设计,今天想就面试而言如何回答好,给面试官好的印象;
首先,在回答这个问题的时候,可以先总体回答GMP是干嘛的,GMP分别指代什么,然后从创建goroutine放置的顺序,调度goroutine的流程阐述,这样一个完整精准的回答,相信会给面试官留下好的印象;

GMP是干嘛的

GMP是用于调度go语言最小执行单元goroutine的调度模型

GMP分别指代什么

G表示Goroutine,go语言的最小执行单元;
M表示Thread,线程的意思
P表示Processer,处理器的意思

GMP三者之间的关系

线程是运行Goroutine的实体,每个调度器对应着一个goroutine本地队列,调度器负责把可运行的Groutine分配到线程上;

创建goroutine流程

当在一个gotounie中执行Go关键字创建一个goroutine时,会优先把这个goroutine当前这个goroutine对应的执行线程所绑定的调度器对应的本地队列里;
如果本地队列满了,会把当前本地队列的前一半和当前创建的这个goroutine打乱顺序后放入全局goroutine队列;

调度goroutine流程

调度器调度goroutine时,会从本地队列中依次取goroutine放到绑定的执行线程执行;
如果本地队列空了,会看全局队列里是否有goroutine,如果有,则取一部分到当前本地队列里,取的数量是min(全局队列g数量/p数量+1,全局g数量/2);
如果全局队列也是空的,则会从其他p对应的本地队列取,这里会从尾部窃取一半的goroutine到本地队列中;
当调度goroutine到执行线程上执行时,如果执行系统调用,则当前M和P会解绑,P会和空闲的M绑定,如果没有空闲的M,则加入到全局P的队列;
当调度goroutine到执行线程上执行时,如果执行阻塞操作(比如channel收发,加锁),则M会和G解绑,M继续执行下一个G,阻塞的G被唤醒时会优先加入P的本地队列,如果满了,会加入到goroutine全局队列;