MST

星途 面试题库

面试题:Go 协程调度器的 GMP 模型详细解析

深入介绍 Go 协程调度器的 GMP 模型,说明 G、M、P 各自代表什么,它们之间是如何相互协作来实现高效的协程调度的,并且举例说明在什么场景下这种协作机制会发挥最大作用。
29.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

GMP 模型简介

在 Go 协程调度器的 GMP 模型中:

  • G(Goroutine):代表协程,它是对用户级线程的抽象。每个 Goroutine 都有自己的栈、程序计数器和局部变量等运行状态。Go 语言通过 go 关键字来创建一个新的 G。例如:
go func() {
    // 这里是协程执行的代码
    fmt.Println("这是一个新的 Goroutine")
}()
  • M(Machine):代表操作系统线程,它是与操作系统内核线程直接对应的实体。M 负责执行 Go 代码,它会从 P 的本地运行队列或者全局运行队列中获取 G 来执行。每个 M 都有一个关联的栈空间,用于执行 Go 函数。
  • P(Processor):代表处理器上下文,它包含了运行 Go 代码所需的资源,如本地运行队列(存放 G)。P 的数量决定了同一时刻可以并发执行的 G 的数量,默认情况下 P 的数量等于 CPU 的核心数。P 还负责调度 G 到 M 上执行。

协作机制

  1. 创建与调度:当使用 go 关键字创建一个新的 G 时,它会被放入到某个 P 的本地运行队列中。如果本地运行队列已满,G 会被放入全局运行队列。
  2. M 与 P 的关联:M 需要获取一个 P 才能执行 G。M 会从空闲的 P 列表中获取一个 P,如果没有空闲的 P,M 可能会进入休眠状态。
  3. 执行 G:M 从 P 的本地运行队列中取出一个 G 来执行。如果本地运行队列空了,M 会尝试从全局运行队列或者其他 P 的本地运行队列中偷取 G 来执行。
  4. G 的阻塞与恢复:当 G 执行系统调用等阻塞操作时,M 会将 G 与 P 分离,此时 M 可以继续执行其他 G。当 G 阻塞结束,它会被重新放回某个 P 的运行队列等待再次执行。

应用场景

  1. 高并发 I/O 操作:例如在一个网络爬虫程序中,需要同时发起大量的 HTTP 请求。每个请求可以作为一个 G 来处理。由于 I/O 操作通常会有较长的等待时间,通过 GMP 模型,当某个 G 因为 I/O 阻塞时,M 可以切换去执行其他 G,从而充分利用 CPU 资源,提高程序的整体效率。
  2. 并行计算:在科学计算领域,当需要对大量数据进行并行处理时,将每个数据块的处理任务作为一个 G。P 的数量与 CPU 核心数匹配,使得每个 CPU 核心都能高效地执行 G,实现并行计算,加速计算过程。