Go语言(Golang)的并发模型基于其独特的调度器,这个调度器被称为GMP(Goroutine, M(Machine,即线程或执行体), P(Processor,即处理器))模型。这个模型是Go语言运行时(runtime)的核心部分,用于高效地管理成千上万的goroutine(轻量级线程)。
下面是对GMP模型各部分的详细解释:
1. Goroutine(G)
Goroutine是Go语言中的并发体,它比线程更轻量级。每个goroutine的栈大小在初始时只有几KB,并且可以根据需要增长和缩小。这使得创建成千上万的goroutine变得非常廉价,并且这些goroutine可以并发执行,以充分利用多核CPU。
2. Machine/Thread(M)
M代表操作系统线程,它是Go运行时与操作系统之间的桥梁。M负责执行G中的代码。在GMP模型中,M的数量是有限的,由Go运行时根据系统负载动态调整。
3. Processor(P)
P代表处理器,它负责调度G到M上执行。P的数量默认等于CPU核心数,但也可以通过环境变量GOMAXPROCS
来设置。每个P都维护了一个可运行的G的队列,以及执行G所需的上下文信息。当M执行完一个G后,它会从P的队列中取出下一个G继续执行,或者如果没有可运行的G,则M会进入休眠状态,等待新的G被调度到P上。
GMP模型的工作流程
当一个新的goroutine被创建时,它会被放入某个P的可运行队列中,如果P队列已满则放入一个全局的队列中。
M会不断地从它关联的P的可运行队列中取出G来执行。
如果P的可运行队列为空,M会尝试从其他P的可运行队列或者全局队列中“偷取”G来执行,如果所有的P都没有可运行的G,M会进入休眠状态。
当一个G因为系统调用或阻塞操作而暂停时,M会释放与P的关联,后再创建一个新的操作系统的线程(如果有空闲的线程可用就复用空闲线程)来服务于这个P
当G执行完毕后,M会再次尝试从P的可运行队列中取出G来执行,不断循环。
通过这种方式,GMP模型能够高效地管理大量的goroutine,使得Go语言在并发编程方面表现出色。
评论区