Go 语言并发模型详解:GMP 调度器工作原理

Leo
Leo
发布时间:2026-10-15| 7人浏览过
原创

Go 语言凭借高效的 goroutine 机制解决了高并发场景下的性能瓶颈。其核心依赖于 GMP 调度模型,通过操作系统线程、逻辑处理器与协程的协作,以及工作窃取算法,实现了轻量级且高性能的并发执行环境。

一、Go 语言的基本并发概念

Go 语言的并发能力允许函数独立于其他函数运行。这种并发同步模型源自 通信顺序进程(Communicating Sequential Processes,CSP)范式。与传统的基于内存锁的同步方式不同,CSP 强调通过消息传递来共享数据。在 Go 中,Channel(通道)是实现 goroutine 之间消息传递的核心工具。

要理解 Goroutine,首先需要厘清进程、线程与传统调度的区别:

  • 进程(Process):包含应用程序运行所需资源的容器,是操作系统资源分配的最小单位。
  • 线程(Thread):CPU 调度的基本单位,拥有独立的执行空间。
  • Goroutine:Go 运行时管理的轻量级执行单元,比线程更节省资源。

补充:什么是句柄?

句柄可理解为指向内核资源的指针。如同门的把手连接着门板,用户通过操作句柄来控制底层的系统资源。在 Go 的底层实现中,操作系统负责在物理 CPU 上调度线程,而 Go 运行时则在其维护的逻辑处理器上调度 goroutine。

二、GMP 调度器核心架构

Go 调度器的核心由四个关键结构体支撑:Sched、M、P 和 G。它们共同协作以维持程序的高效运行。

  • Sched:全局调度器状态,维护存储 M 和 G 的全局队列及调度状态信息。
  • M (Machine):代表内核级操作系统线程。它是实际执行代码的主体,绑定了当前运行的 goroutine、本地缓存(mcache)等。
  • P (Processor):逻辑处理器,用于管理 goroutine 的执行队列。每个 P 维护一个本地运行队列,并绑定到一个 M 上。
  • G (Goroutine):协程的核心结构,包含栈、程序计数器(PC)及所属的 M 信息等。

生动比喻:地鼠搬运工

为了直观理解 GMP 的关系,可以将其比作一个工地场景:

  • M(地鼠):真正干活的搬运工。
  • P(小车):地鼠使用的搬运工具,装载待处理的砖块。
  • G(砖块):需要处理的goroutine任务。

调度流程详解

整个调度过程遵循以下逻辑:

第1步:本地获取(runqget)

地鼠(M)首先尝试从自己的小车(P)中取一块砖(G)。如果小车已空,则进入下一步。

第2步:寻找可用任务(findrunnable)

若本地无砖,地鼠会去工场仓库(全局队列)取砖。如果仓库也没砖,它会尝试“偷”隔壁同事小车的砖(Work Stealing 算法),通常取走一半。若多次尝试失败,说明系统空闲,地鼠会将小车归还停车场并休眠。

第3步:唤醒新工作者(wakep)

当手头任务堆积过多时,地鼠会检查是否有闲置的小车。若有,它还会叫醒正在睡觉的同事(或其他M)来分担工作;若没有,则会向工场老板(操作系统)请求新建线程。

第4步:执行任务(execute)

地鼠将砖块放入火炉进行加工,即执行 goroutine 代码。

注:“地鼠偷砖”对应的是调度算法中的 work stealing,旨在平衡负载。

三、Goroutine 的阻塞与恢复

当某个 OS 线程 M0 被阻塞(如 I/O 操作)时,为了避免 P 闲置,Go 调度器会将当前的 P 转移给另一个可用的 OS 线程 M1 继续执行。此时,原线程 M0 虽处于等待状态,但其绑定的 P 仍在处理其他任务。

当阻塞解除后,该 goroutine 需重新获取一个 P 才能继续运行。通常情况下,它会从其他忙碌的 M 处“抢”一个 P;若无可用 P,则将其加入全局运行队列,自身进入休眠(放入线程缓存)。

此外,系统还会动态调整负载:如果一个线程满载而另一个空闲,P 会被重新分配,以实现负载均衡。

参考来源:https://morsmachine.dk/go-scheduler

四、并发与并行的区别

许多初学者容易混淆这两个概念,它们的本质区别如下:

  • 并发(Concurrency):指两个或多个任务在重叠的时间段内启动、运行和完成。侧重于结构上的组织,即程序能同时处理多个任务,但不一定在同一时刻执行。
  • 并行(Parallelism):指多个任务在同一时刻同时进行计算。侧重于时间上的同步,通常依赖于多核 CPU。

简单来说:并发是让一堆事情看起来都在做(通过快速切换);并行是真正同时做多件事。

  • 仅并发:单核上通过分时复用处理多任务。
  • 仅并行:多核上同时执行不相关的子任务。
  • 既并发又并行:多核 CPU 上同时运行多个并发任务流。

以上就是 Go 语言中 Goroutine 基本原理、GMP 调度器工作流程及并发并行概念的详细内容,更多关于 Go 并发编程的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。