goroutine 调度器 GPM

goroutine 调度器 GPM #

image image

  • 全局队列(Global Queue):存放等待运行的G。
  • P的本地队列:同全局队列类似,存放的也是等待运行的G,存的数量有限,不超过256个。新建G’时,G’优先加入到P的本地队列,如果队列满了,则会把本地队列中一半的G移动到全局队列。
  • P列表:所有的P都在程序启动时创建,并保存在数组中,最多有runtime.GOMAXPROCS个。
  • M:线程想运行任务就得获取P,从P的本地队列获取G,P队列为空时,M也会尝试从全局队列拿一批G放到P的本地队列,或从其他P的本地队列偷一半放到自己P的本地队列。M运行G,G执行之后,M会从P获取下一个G,不断重复下去。

Goroutine调度器和OS调度器是通过M结合起来的,每个M都代表了1个内核线程,OS调度器负责把内核线程分配到CPU的核上执行。

P(Processor) 的数量由 GOMAXPROCS 来决定。也就是说同一时间内仅能有 GOMAXPROCS 个 goroutine 在并行运行。

M(Thread) 的数量默认为 10000(OS 一般无法支撑这么多的线程数) ,通过 runtime/debugSetMaxThread 可以设置 M 的数量。

当 P 需要 M ,但所有的 M 都阻塞了,P 就会创建出新的 M 来执行任务。

因此一般来说,会将 runtime.GOMAXPROCS 设置为机器 CPU 核数,那么就会有 CPU 核数个 P(Processor) 。而 M 和 G 都是不定的。

References #