[每周一更]-(第51期):Go的调度器GMP

在这里插入图片描述

参考文献

  • https://learnku.com/articles/41728
  • http://go.cyub.vip/gmp/gmp-model.html#g-m-p
  • https://blog.csdn.net/ByteDanceTech/article/details/129292683
  • https://www.ququ123.top/2022/04/golang_gmp_principle/

什么是GMP?

GMP模型是Go语言并发模型的核心概念,用于管理和调度Goroutine的执行。它包含三个主要组件:Goroutine(协程)、M(机器)和P(处理器)。

Go 为了自身 goroutine 执行和调度的效率,自身在 runtime 中实现了一套 goroutine 的调度器

G-M-P分别代表:
  • G - Goroutine,Go协程,是参与调度与执行的最小单位
  • M - Machine,指的是系统级线程,每个M绑定到一个操作系统线程上。M负责调度和管理Goroutine,它会将Goroutine分配给可用的P进行执行。一个Go程序通常会有多个M,用于实现并发执行。
  • P - Processor,指的是逻辑处理器,P关联了的本地可运行G的队列(也称为LRQ),最多可存放256个G。P负责管理和执行Goroutine,它与M是一对一的关系。P维护了一个Goroutine队列(runqueue),它从队列中获取Goroutine并分配给M执行。
    在这里插入图片描述
G-M-P的数量
  • G 的数量:
    理论上没有数量上限限制的。查看当前G的数量可以使用runtime. NumGoroutine()

  • P 的数量:
    由启动时环境变量 $GOMAXPROCS 或者是由runtime.GOMAXPROCS() 决定。这意味着在程序执行的任意时刻都只有 $GOMAXPROCS 个 goroutine 在同时运行。

  • M 的数量:
    go 语言本身的限制:go 程序启动时,会设置 M 的最大数量,默认 10000. 但是内核很难支持这么多的线程数,所以这个限制可以忽略。 runtime/debug 中的 SetMaxThreads 函数,设置 M 的最大数量 一个 M 阻塞了,会创建新的 M。M 与 P 的数量没有绝对关系,一个 M 阻塞,P 就会去创建或者切换另一个 M,所以,即使 P 的默认数量是 1,也有可能会创建很多个 M 出来。

GMP的工作模式

  • 首先创建一个新的 goroutine
  • 如果本地的局部队列中有足够的空间可以存放,则放入局部队列中;如果局部队列满,则放入一个全局队列(所有的 M 都可以从全局队列中拉取 G 来执行)
  • 所有的 G 都必须在 M 上才可以被执行,M 和 P 存在一一绑定的关系,如果 M 绑定的 P 中存在可以被执行的 G,则从 P 中拉取 G 来执行;如果 P 中为空,没有可执行的 G,则 M 从全局队列中拉取;如果全局队列也为空,则从其他的 P 中拉取 G
  • 为 G 的运行分配必要的资源,等待 CPU 的调度
  • 分配到 CPU,执行 func(){}
    在这里插入图片描述
调度过程中阻塞

GMP模型的阻塞可能发生在下面几种情况:

  • I/O,select
  • block on syscall
  • channel
  • 等待锁
  • runtime.Gosched()
用户态阻塞

当goroutine因为channel操作或者network I/O而阻塞时(实际上golang已经用netpoller实现了goroutine网络I/O阻塞不会导致M被阻塞,仅阻塞G),对应的G会被放置到某个wait队列(如channel的waitq),该G的状态由_Gruning变为_Gwaitting,而M会跳过该G尝试获取并执行下一个G,如果此时没有runnable的G供M运行,那么M将解绑P,并进入sleep状态;当阻塞的G被另一端的G2唤醒时(比如channel的可读/写通知),G被标记为runnable,尝试加入G2所在P的runnext,然后再是P的Local队列和Global队列。

系统调用阻塞

当G被阻塞在某个系统调用上时,此时G会阻塞在_Gsyscall状态,M也处于 block on syscall 状态,此时的M可被抢占调度:执行该G的M会与P解绑,而P则尝试与其它idle的M绑定,继续执行其它G。如果没有其它idle的M,但P的Local队列中仍然有G需要执行,则创建一个新的M;当系统调用完成后,G会重新尝试获取一个idle的P进入它的Local队列恢复执行,如果没有idle的P,G会被标记为runnable加入到Global队列。

一种形象的栗子

地鼠(Gopher)的工作任务是:工地上有若干砖头,地鼠借助小车把砖头运送到火种上去烧制。M 就可以看作图中的地鼠,P 就是小车,G 就是小车里装的砖。
弄清楚了它们三者的关系,下面我们就开始重点聊地鼠是如何在搬运砖块的。

  • Processor(P):
    根据用户设置的 GoMAXPROCS 值来创建一批小车§。
  • Goroutine(G):
    通过 Go 关键字就是用来创建一个 Goroutine,也就相当于制造一块砖(G),然后将这块砖(G)放入当前这辆小车§中。
  • Machine (M):
    地鼠(M)不能通过外部创建出来,只能砖(G)太多了,地鼠(M)又太少了,实在忙不过来,刚好还有空闲的小车§没有使用,那就从别处再借些地鼠(M)过来直到把小车§用完为止。
    这里有一个地鼠(M)不够用,从别处借地鼠(M)的过程,这个过程就是创建一个内核线程(M)。
    需要注意的是:地鼠(M) 如果没有小车§是没办法运砖的,小车§的数量决定了能够干活的地鼠(M)数量,在 Go 程序里面对应的是活动线程数;
    在这里插入图片描述

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

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

相关文章

Debezium发布历史43

原文地址: https://debezium.io/blog/2018/12/05/automating-cache-invalidation-with-change-data-capture/ 欢迎关注留言,我是收集整理小能手,工具翻译,仅供参考,笔芯笔芯. 通过更改数据捕获自动使缓存失效 2018 年…

计算机基础面试题 |06.精选计算机基础面试题

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

k8s的陈述式管理

k8s的陈述式管理: 所谓的陈述式管离也就是命令行工具 优点:90%以上都可以满足 对资源的增删查比较方便,对改不是很友好 缺点:命令比较冗长,复杂,难记 声明式: k8s当中的YAML文件来实现资源管…

SpringBoot整合ElasticSearch实现CRUD操作

本文来说下SpringBoot整合ES实现CRUD操作 文章目录 概述项目搭建ES简单的crud操作本文小结 概述 SpringBoot支持两种技术和es交互。一种的jest,还有一种就是SpringData-ElasticSearch。根据引入的依赖不同而选择不同的技术。反正作为spring全家桶,目前是…

数仓可视化5--superset的部署安装

1、superset简介 Apache Superset 是一个现代的数据探索和可视化平台。它功能强大且十分易用,可对接各种数据源,包括很多现代的大数据分析引擎,拥有丰富的图表展示形式,并且支持自定义仪表盘。 2、安装步骤 2.1、安装Miniconda3 …

冒泡排序-排序算法

前言 如果有6个人站成一排,要将他们按从矮到高的顺序排列。你可能有多种方式来完成。但是如果其中有一个人特别高,比他身边的人高,在队伍中特别明显,你可以轻易看出那个最高的需要和身边的人交换位置,这是冒泡排序的核…

aspose通过开始和结束位置关键词截取word另存为新文件

关键词匹配实体类: Data EqualsAndHashCode(callSuper false) public class TextConfig implements Serializable {private static final long serialVersionUID 1L;/*** 开始关键词,多个逗号分隔*/private String textStart ;/*** 结束关键词&#x…

【HBuilder + IDEA + XFtp + XShell】打包部署上线

简述 前后端分离:需要将前后端的程序包打包发送至应用Linux服务器上Linux服务器 (1)需要启用SSHD服务,该服务会监听22号端口(一般是开启的) (2)搭建:MYSQL、Nginx、jdk、…

IPA打包过程中的Invalid Bundle Structure错误如果解决

在iOS应用程序开发中,打包和发布应用程序是一个必要的步骤。有的时候在打包的过程中可能会遇到一些错误,其中一个比较常见的错误是"Invalid Bundle Structure"。这个错误通常意味着应用程序的文件结构不正确,而导致的无法成功打包应…

基于深度卷积神经网络的猴痘分类识别系统

温馨提示:文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 本文详细介绍了一基于深度卷积神经网络的猴痘分类识别系统。采用TensorFlow和Keras框架,通过卷积神经网络(CNN)进行模型训练和预测,利用迁移学习中的…

Linux 系统编程:文件系统

文件类型 Linux 文件分为 3 类: 普通文件:文本文件、二进制文件,要学习如何创建、复制、移动、重命名和删除这样的文件。目录(Windows 中的“文件夹”与之类似)伪文件:设备文件、命名管道、proc 文件&…

Simple Facebook Sign-In

简单的Facebook登录为Android、iOS、Windows、Mac、通用Windows平台(UWP)和Unity制作的WebGL应用程序提供了基于OAuth 2.0的Facebook登录。 优点: ● 跨平台游戏和应用程序的跨平台用户身份验证 ● 无插件,无第三方库,无依赖● 对建筑规模没有影响 ● 客户端-服务器应…