内容来源:Go语言从入门到项目实践-电子工业出版社
GMP,是三个组建的缩写,即Goroutine(协程),Processor(任务处理器)和Machine(线程)。三者相互协调,共同完成任务调度。Processor是协程和线程之间的桥梁,如果某个线程想要运行Goroutine任务,必须先访问Processor,通过Processor获取Goroutine任务队列,最终使得某个Goroutine得到执行。
整个GPM设计架构如图所示。
-
全局队列中包含所有排队的Goroutine任务。 - G指单个Goroutine任务。
- Processor队列是分配好的排队中的Goroutine任务,且每个Processor队列最多不超过256个任务。所有新创建的Goroutine任务都会先尝试加入Processor队列中。若一个Processor队列满了,则会把该队列中一般的Goroutine任务移动至全局队列中。
- P指Processor,所有Processor在程序启动时被创建,并被保存在数组中。开发者可以通过runtime包中的GOMAXPROCS()函数配置Processor总个数。
- M指Machine,是内核线程。内核线程会先尝试从Processor队列中获取单个Goroutine任务,并执行该任务。当Processor队列为空时,内核线程会尝试从全局队列中获取若干个Goroutine任务并添加到该Processor队列中,或者尝试从其他Processor队列中获取一半数量的Goroutine任务并添加到该Processor队列中,然后获取单个Goroutine任务,并执行该任务。在任务被执行后,重复上述操作。内核线程的个数默认为10000,但是由于内核很难达到这么多的线程数量,因此该值意义不大。
当某个内核线程发生阻塞时,Processor就会创建新的内核线程或切换至另一个内核线程来执行。因此,Processor的数量与内核线程的数量并不完全相等,通常内核线程的数量会多于Processor的数量。
Processor在确定其最大数量值后,运行时会立刻根据最大数量值创建多个Processor。内核线程的创建时机是当没有足够的内核线程来关联Processor时,或者内核线程发生阻塞且没有空闲的其他内核线程时。