来源:go-interview / Go

Go语言的GPM调度模型是Go运行时中用于处理并发的核心机制之一,它将Goroutine(轻量级线程)有效地映射到系统线程上,以最大化并发性能。GPM模型主要由三个部分组成:G(Goroutine)、P(Processor)、M(Machine)。让我们逐一详细介绍:

1. G(Goroutine)

  • Goroutine 是Go语言中用于并发执行的轻量级线程,每个Goroutine都有自己的栈和上下文信息。
  • Goroutine相对于操作系统的线程更加轻量级,可以在同一时间内运行成千上万的Goroutine。

2. P(Processor)

  • P 是处理Goroutine的调度器的上下文,每个P包含一个本地运行队列(Local Run Queue),用于存储需要运行的Goroutine。
  • P的数量由GOMAXPROCS设置决定,它决定了并行执行的最大线程数。
  • P不仅管理Goroutine,还负责与M协作,将Goroutine分配给M执行。

3. M(Machine)

  • M 代表操作系统的线程,负责执行Goroutine。一个M一次只能执行一个Goroutine。
  • M是实际执行代码的工作单元,M与P绑定后才能执行Goroutine。
  • M可以通过调度器从全局运行队列中拉取新的Goroutine,也可以与其他M协作完成工作。

4. GPM模型的调度过程

  • 调度器工作机制:Goroutine创建后会被放入P的本地队列,P会从该队列中选择Goroutine,并将其分配给M执行。如果本地队列为空,P可以从全局运行队列或其他P的队列中窃取任务。
  • 工作窃取机制:如果一个P的本地队列为空,而另一个P的本地队列中有多个Goroutine,前者可以从后者中窃取任务,从而保持系统的高效利用率。
  • 阻塞与调度:当M执行的Goroutine阻塞(例如I/O操作)时,M会释放当前的P并等待P重新分配任务,从而避免资源浪费。

5. 模型优点

  • 高效的并发调度:GPM模型使得Go语言可以高效地管理数百万个Goroutine的并发执行。
  • 可伸缩性:通过P与M的动态调度,GPM模型可以充分利用多核处理器的性能。
  • 轻量级:Goroutine非常轻量,创建和切换的成本比系统线程要低得多。