今天看 studygolang.com 一篇讲解 GMP 的文章时,对一个细节有疑问。
线程想运行任务就得获取P,从P的本地队列获取G,P队列为空时,M也会尝试从全局队列拿一批G放到P的本地队列,或从其他P的本地队列偷一半放到自己P的本地队列。M运行G,G执行之后,M会从P获取下一个G,不断重复下去。
那当P队列为空时,M是先从全局队列拿G放到P的本地队列,还是先从其它P窃取?
通过查阅相关资料,发现《Go专家编程》一书也没有明确说明。里面有一句话:
GO调度器提供了工作量窃取策略,即当某个处理器P没有需要高度的协程时,将从其它处理器中偷取协程,……
从讲解的顺序猜测可能是会先从全局队列取,直到没有新的需要执行的协程再去其它P偷取。
再查阅刘丹冰写的《Golang修养之路》电子书,找到以下介绍:
全局队列已经没有G,那m就要执行work stealing(偷取):从其他有G的P哪里偷取一半G过来,放到自己的P本地队列。P2从P1的本地队列尾部取一半的G,本例中一半则只有1个G8,放到P2的本地队列并执行。
前面的设想是对的:先从全局队列获取。
后面有空得再通读一遍实现的源码,加深一下理解。