Golang GMP
GMP
G:goroutine
M:machine(thread)
P:processor
全局队列: 存放等待运行的G。
P的本地队列:存放等待运行的G, 有数量限制,优先将新创建的G放在P的本地队列中,如果满了放在全局队列中。
P列表:程序启动时创建,最多有GOMAXPROCS个(可设置)。
M列表:当前操作系统分配到当前Go程序的内核线程数。
P的数量可通过:1.环境变量 $GOMAXPROCS,2.在程序中通过runtime.GOMAXPROCS()来设置
M的数量可通过: runtime/debug包中的SetMaxThreads函数来设置,Go语言本身设定M的最大量是10000,一般忽略。有一个M阻塞,会创建一个新的M,有一个M空闲,会回收或者睡眠。
调度器的设计策略:
1.复用线程: work stealing机制【P已经将G全部执行完,然后去查询全局队列,全局队列中也没有G,而另一个M中除了正在运行的G外,队列中还有3个G待运行。此时,空闲的P会将其他P中的G偷取一部分过来,一般每次偷取一半。】,hand off机制【当本线程M0因为G0进行系统调用阻塞时,线程释放绑定的P,把P转移给其他空闲的线程执行。 进而某个空闲的M1获取P,继续执行P队列中剩下的G。 而M0由于陷入系统调用而进被阻塞,M1接替M0的工作,只要P不空闲,就可以保证充分利用CPU。 M1的来源有可能是M的缓存池,也可能是新建的。】
2.利用并行
3.抢占
4.全局G队列