背景![](https://i-blog.csdnimg.cn/blog_migrate/dee9c7da96958b4b6ed10bd8b6c4c527.png)
原理
我们先理解什么是G、M、P
G∶goroutine,一个计算任务。由需要执行的代码和其上下文组成,上下文包括∶当前代码位置,栈顶、栈底地址,状态等。
M∶ machine,系统线程,执行实体,想要在CPU上执行代码,必须有线程,与C语言中的线程相同,通过系统调用 clone 来创建。
P:processor,虚拟处理器,M必须获得P才能执行代码,否则必须陷入休
眠(后台监控线程除外),你也可以将其理解为一种 token,有这个 token,才有在物理 CPU核心上执行的权力。
Go的调度流程本质上是一个生产-消费流程
如上图所示,当我写一个go func的时候就好像我们在往队列里添加了一条数据
P会有一个三级队列
第一级是runext
第二级是local run queue
第三级是global run queue(全局队列)
这些队列就是用来存储我们写一次go func的时候就会生成一个G
那这些G的生成顺序和消费顺序是怎么样的?
一个新的G进来,它是如何存放的呢?