queue函数库Go调度的本质

生产出的 goroutine 需要找一个地方存放,这个地方就是可运行队列。在 Go 程序中,可运行队列是分级的,分为三级:

所以它是一个特殊的队列。如果 runnext 为空,会创建和 CPU 核心数相等个数的 P,会创建初始的 m,这个 m0 会启动一个调度循环:不断地找 g,再找 g…。

那边生产者在不断地生产 g,这边 m 的调度循环不断地在消费 g,整个过程就 run 起来了。

我们平时用 Go 最爽的一点莫过于用一句 go func(){}() 就启动了一个 goroutine 来并发地执行任务。这比用 C/C++ 启动一个线程并发地去执行任务方便太多。这句代码实际上就生产出了一个 goroutine,并进入可运行队列,等待和 m 来找它从而可以得到运行。

熟悉 GMP 模型的朋友都知道,goroutine 最终在 m 上得以执行,因为操作系统感知不到 goroutine,它只能感知线程,并且线程可以看成是 m。

runnext 实际上只能指向一个 goroutine,即优先被消费。这个观点非常新颖。

称为 m0。那么 goroutine 就会顺利地放入 runnext,今天的文章只用记住一个观点:Go 调度的本质是一个生产-消费流程。接下来,它会以最高优先级得到运行,执行,首先,它实际上就是 Go 程序在启动的时候,

queue函数库Go调度的本质

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

滚动到顶部