GO GMP

GMP

为了解决 Go 早期多线程 M 对应多协程 G 调度器的全局锁、中心化状态带来的锁竞争导致的性能下降等问题,Go 开发者引入了处理器 P 结构,形成了当前经典的 GMP 调度模型。

  • GMP 模型是 Go 语言调度器采用的并发编程模型
  • 它包含三个重要的组件:Goroutine(G)、操作系统线程(M)和逻辑处理器(P)
  • Go 调度器:运行时在用户态提供的多个函数组成的一种机制,目的是高效地调度 G 到 M上去执行

组成

  • Goroutine (G) 是 Go 语言中轻量级的并发执行单元,类似于线程但比线程更小、更灵活。每个 goroutine 都有自己独立的堆栈和寄存器等信息,可以通过 go 关键字创建并发执行任务。
  • 逻辑处理器(P)是一个虚拟的执行单元,负责调度 goroutine 和执行 Go 代码。Go 程序中有多个 P,每个 P 可以运行多个 goroutine,因此可以实现真正的并发执行。
  • 操作系统线程(M)是实际的执行单元,负责将 goroutine 调度到逻辑处理器上执行。Go 程序中通常会创建多个 M,以便在多核 CPU 上实现并发执行。

GMM

调度场景

  1. 创建 G:

    • 正在 M1 上运行的P1,有一个G1
    • G1 通过go func() 创建 G2
    • 由于局部性,G2优先放入P1的本地队列
  2. G 运行完成后:

    • M1 上的 G1 运行完成后
    • M1 上运行的 Goroutine 会切换为 G0
    • G0 从 M1 上 P1 的本地运行队列获取 G2 去执行
    • 注:这里 G0 是程序启动时的线程 M(也叫M0)的系统栈表示的 G 结构体,负责 M 上 G 的调度
  3. M 上创建的 G 个数大于本地队列长度时:

    • P 本地队列最多能存 256 个G
    • 正在 M1 上运行的 G2 要通过go func()创建 258 个G,前 256 个G 放在 P1 本地队列中
    • G2 创建了第 257 个 G(G259)时,P1 本地队列中前一半和 G259 一起打乱顺序放入全局队列,P 本地队列剩下的 G 往前移动
    • G2 创建的第 258 个 G(G260)时,放入 P 本地队列中,因为还有空间
  4. M 的自旋状态:

    • 创建新的 G 时,运行的 G 会尝试唤醒其他空闲的 M 绑定 P 去执行
    • 如果 G2 唤醒了M2,M2 绑定了一个 P2,会先运行 M2 的 G0
    • 这时 M2 没有从 P2 的本地队列中找到 G,会进入自旋状态(spinning)
    • 自旋状态的 M2 会尝试从全局 P 队列里面获取 G,放到 P2 本地队列去执行
    • 获取的数量满足公式:n = min(len(globrunqsize)/GOMAXPROCS + 1, len(localrunsize/2))
    • 含义是每个P应该从全局队列承担的 G 数量,为了提高效率,不能太多,要给其他 P 留点
  5. 任务窃取机制:

    • 自旋状态的 M 会寻找可运行的 G
    • 如果全局队列为空,则会从其他 P 偷取 G 来执行,个数是其他 P 运行队列的一半
  6. G 发生系统调用时:

    • 如果 G2 发生系统调度进入阻塞,其所在的 M1 也会阻塞:因为会进入内核状态等待系统资源
    • 和 M1 绑定的 P1 会寻找空闲的 M 执行:这是为了提高效率,不能让 P 本地队列的 G 因所在 M 进入阻塞状态而无法执行
    • 注:M1 上的 G2 如果是进入 Channel 阻塞,则该 M 不会一起进入阻塞,因为 Channel 数据传输涉及内存拷贝,不涉及系统资源等待
  7. G 退出系统调用时:

    • 如果刚才进入系统调用的 G2 解除了阻塞
    • 其所在的 M1 会寻找 P 去执行,优先找原来的 P1
    • 如果没有找到,则其上的 G2 会进入全局队列,等其他 M 获取执行,M1 进入空闲队列

基于 GMP 模型的 Go 调度器的核心思想是:

  1. 尽可能复用线程 M:

    • 避免频繁的线程创建和销毁;
  2. 利用多核并行能力:

    • 限制同时运行(不包含阻塞)的 M 线程数为 CPU 的核心数目
    • 通过设置 P 处理器的个数为 GOMAXPROCS 来保证,GOMAXPROCS 一般为 CPU 核数
    • 因为 M 和 P 是一一绑定的,没有找到 P 的 M 会放入空闲 M 列表,没有找到 M 的 P 也会放入空闲 P 列表
  3. Work Stealing 任务窃取机制:

    • M 优先执行其所绑定的 P 的本地队列的 G
    • 如果本地队列为空,可以从全局队列获取 G 运行,也可以从其他 M 绑定的 P 中偷取 G 来运行
  4. Hand Off 交接机制:

    • M 阻塞,会将 M 上 P 的运行队列交给其他 M 执行
    • 交接效率要高,才能提高 Go 程序整体的并发度
  5. 基于协作的抢占机制:

    • 每个真正运行的G,如果不被打断,将会一直运行下去
    • 为了保证公平,防止新创建的 G 一直获取不到 M 执行造成饥饿问题
    • Go 程序会保证每个 G 运行10ms 就要让出 M,交给其他 G 去执行
  6. 基于信号的真抢占机制:

    • 尽管基于协作的抢占机制能够缓解长时间 GC 导致整个程序无法工作和大多数 Goroutine 饥饿问题
    • 但是还是有部分情况下,Go调度器有无法被抢占的情况,例如,for 循环或者垃圾回收长时间占用线程
    • 为了解决这些问题, Go1.14 引入了基于信号的抢占式调度机制,能够解决 GC 垃圾回收和栈扫描时存在的问题。

参考文章:深入分析Go1.18 GMP调度器底层原理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/512592.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

独立站营销攻略:塑造品牌,掌控数据,应对挑战

随着出海热的加剧,独立站已成为品牌拓展海外市场的重要组成部分。独立站不仅能够帮助企业建立品牌形象,扩大市场份额,还能够提高用户忠诚度和品牌认知度。然而,独立站在推广营销方面也有着诸多挑战,如流量获取、用户粘…

测试需求平台10-DBUtils 优化数据连接与 SQL Limit 实现分页

✍此系列为整理分享已完结入门搭建《TPM提测平台》系列的迭代版,拥抱Vue3.0将前端框架替换成字节最新开源的arco.design,其中约60%重构和20%新增内容,定位为从 0-1手把手实现简单的测试平台开发教程,内容将囊括基础、扩展和实战&a…

2191. 数字梯形问题(网络流,费用流,最大权不相交路径)

活动 - AcWing 给定一个由 n 行数字组成的数字梯形如下图所示。 梯形的第一行有 m 个数字。 从梯形的顶部的 m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径。 规则 1:从梯形的顶至底的 m 条路径互不相…

隧道技术和代理技术(一)

目录 基础知识 单机-防火墙-限制协议出入站 域控-防火墙-组策略对象同步 域控-防火墙-组策略不出网上线 基础知识 -隧道技术:解决不出网协议上线的问题(利用出网协议进行封装出网) -代理技术:解决网络通讯不通的问题&#xf…

职场卷王:我用可视化大屏模板做工作汇报,惊艳了同事和领导。

2023结束了,我和我的小伙伴们纷纷开始忙碌的年终总结和汇报。 正忙着汇总Excel数据、写word讲稿、找PPT模板时,我发现隔壁组的老王独自在大会议室偷偷调试起了那台汇报用的电视机。 不会吧不会吧,年终汇报还有一周呢,这家伙PPT都…

web组态--新一代全流程低代码物联网平台

先上图,实际完成效果: 1.添加应用图纸 登录by组态后台:http://www.byzt.net:90 ​ 点击组态管理-画面管理,先新建一个组态画面,填写画面名称,保存,进入组态画面。 ​ 选择画面管理&#xff…

mysql高可用架构设计

一、主从架构 主从架构一般如下所示 这里从节点一般设置成只读(readonly)模式。这样做,有以下几个考虑: 有时候一些运营类的查询语句会被放到备库上去查,设置为只读可以防止误操作; 防止切换逻辑有 bug&a…

MySQL:一行记录如何

1、表空间文件结构 表空间由段「segment」、区「extent」、页「page」、行「row」组成,InnoDB存储引擎的逻辑存储结构大致如下图: 行 数据库表中的记录都是按「行」进行存放的,每行记录根据不同的行格式,有不同的存储结构。 页…

微服务架构 | 多级缓存

INDEX 通用设计概述2 优势 通用设计概述 通用设计思路如下图 内容分发网络(CDN) 可以理解为一些服务器的副本,这些副本服务器可以广泛的部署在服务器提供服务的区域内,并存有服务器中的一些数据。 用户访问原始服务器时&#x…

Kafka | SpringBoot集成Kafka

SpringBoot集成Kafka 一、前言二、项目1. pom2. application.properties4. 消息生产者-测试5. 消息消费者 三、启动测试四、有总结的不对的地方/或者问题 请指正, 我在努力中 一、前言 该文章中主要对SpringBoot 集成Kafka 主要是 application.properties 与 pom坐标就算集成完…

【无刷电机学习】光耦HCNR200基本原理及应用(资料摘抄)

【仅作自学记录,不出于任何商业目的。如有侵权,请联系删除,谢谢!】 本文摘抄翻译自: https://docs.broadcom.com/wcs-public/products/application-notes/application-note/331/6/av02-1333en-an_5394-16jul10.pdfhtt…

ruoyi-vue-plus4.X版本实现内嵌swagger文档(简单解决方法)

1.在common模块中添加pom依赖 <dependency><groupId>org.webjars</groupId><artifactId>swagger-ui</artifactId><version>4.15.5</version></dependency>结果如下&#xff1a; 2.在ResourcesConfig配置类的addResourceHandl…