什么是golang调度模型:
golang调度模型即两级线程模型,是由G(goroutine)P(资源)M(工作线程,KSE绑定)三元素构成。M个G对N个M
设计策略:
复用线程 利用并行 抢占 全局G队列
work stealing机制 hand off机制
调度流程:(调度器模型图)
每个M都包含一个g0(系统栈)和g(信号栈),这些称为系统g,M上其他的G则称为用户G。(go的角度)一个go func()创建,会首先加入P的本地可运行队列,P的可运行队列满了,就会导致P的本地队列的前半部分打乱顺序和先创建的G一起放入调度器的可运行队列。被M拿到后开始执行,销毁,然后开启新一轮调度帮助M获取其他的G。(如果此时G发生systemCall阻塞,此时M会锁定G,与当前的P解绑,唤醒或创建一个新的M,来绑定当前的P。等到这个G从系统调用退出时,判断是否可执行,可以继续执行,不行就放到调度器的可执行队列中)
(全局的角度)(一系列初始化完成后,会开启第一轮调度,此时会首先执行含有main函数的go代码,然后就会到go的创建一系列流程。schedule()函数会先从M开始,1 如果发现当前M已经与G锁定,此时检测G的状态,不可运行就停止此轮调度,可运行就执行这个G 2 没有绑定G,检查是否执行串行运行时任务(垃圾回收中的子任务,panic任务),没有则继续 。检查是否存在执行追踪读取任务的G;检查是否有执行GC标记任务的G;检查计数器是否为61的倍数,是的话在调度器的G可运行队列获取;检查P的本地G可运行队列中是否有可运行的G,没有就会进行阻塞,执行findrunnable()方法;
全力查找可运行G详细分为2个阶段10个步骤
1 是否可以在执行终结器获取G 2是否可以在本地可运行队列获取G 3是否在全局G可运行队列获取G 4I/O轮训器中获取G 5 去其他P偷取 6 检查是否有GC标记的G 78910
调度场景:
创建一个M
结束一个go
解决了什么问题
栈管理和抢占