Golang GMP 模型 Work-Stealing

浏览:57次阅读
没有评论

GMP 模型说明

Goroutine 调度器的工作是将准备运行的 goroutine 协程分配到正确的工作线程中, 然后投递给对应的某个绑定的核心执行

G

G 代表的是 golang 中的协程 goroutine, 是 Golang 对协程概念的抽象, 居于以下特点

  • 相比线程而言, 他是一个轻量级的版本的线程
  • 拥有自己的栈空间, 状态, 以及执行的任务函数
  • 每一个 G 会分配到一个可用的 P, 并且在 M 上运行

M

M (Machine), 代表是工作线程, 他是操作系统内核线程, 用于和操作系统调度器进行交互, 他的作用是将 P 获取到的 G 协程投递到 CPU 某核进行执行, 他具有以下特点

  • M 是 Golang 与操作系统之间的桥梁, 他分支执行 P 分配给他的 G
  • M 的数量一般会根据系统资源进行调整
  • M 可能会被特定的 G 通过 LockOSThread 锁定, 这种 G 和 M 的绑定确保了特定 Goroutine 可以持续使用同一个线程
  • M 会有一个进入自旋状态, 循环查询空闲的 P 列表, 如果获取到了 P, 那么就会解除自旋的状态, 且分配一个线程 M

P

P 是一个 Goroutine 的调度器, 每个 P 拥有一个本地队列, 依次进行投递给 M, P 的数量由 GOMAXPROCS(N) 控制, 默认情况下为当前核数量, 他具有以下特点

  • P 是 G 的执行上下文, 他有一个本地队列存储待执行的 G, 负责分配 M 执行那个 G
  • P 的数量默认情况是根据环境变量 GOMAXPROCS 决定, 如果数量大于 CPU 的物理线程数量将没有什么意义
  • M 必须绑定一个 P 才能执行 Go 代码, 但是 M 可以在没有绑定 P 的情况下执行系统调用或者被阻塞
  • P 最大队列长度为 256

P 队列

其中已知 P 会有自己的一个本地队列, 那么系统还有一个 全局的 G 队列, 此队列因为多线程会抢占数据, 所以会有一个锁
P 的本地队列接近无锁的状态, 只有在 Work Stealing 状态下会锁

Work Stealing 机制

在 P 本地队列获取完成后会从全局队列中获取一批 G, 如果全局队列没有了, 那么会从其他 P 队列相对较多的地方偷一半的 G 到本 P 的本地队列中

Golang GMP 模型 Work-Stealing

正文完
 0
包子
版权声明:本站原创文章,由 包子 于2025-02-13发表,共计807字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)