go学习-GMP模型

GMP 好理解还是 GPM 好理解?

在这里插入图片描述
按照上述图,从上往下,GPM更适合理解
GMP 模型: Go 语言运行时系统中的 Goroutine、用于管理 Goroutine 调度的 Go Scheduler(P)、机器可用的逻辑处理器数量(M)。

理解GPM

G

每个 Goroutine 是一个轻量级“线程”,称之为“协程”,可由 Go 运行时系统并发执行

G与P的关系

Goroutine 通过 Go Scheduler 调度运行
Go Scheduler 负责在适当时间调度 Goroutine 的执行
并在必要时将 Goroutine 阻塞和调度到其他 Goroutine 执行上下文

P

P 是中介者,连接 Goroutine 和 M,由于 Go Scheduler 在用户 CPU 时间片内并行执行 Goroutine,因此也必须用 P 进行有效的调度。
Go 运行时系统可以自动调整 P 的数量,以确保它们与当前运行的 Goroutine 的数量大致相同,并且可以在需要更多/更少 P 时及时适应。

P 叫 go运行时的逻辑并发单元,每个OS线程需要获取一个P才能执行
每个P中都包含运行一个线程所需的全部资源(比如线程栈),包括存放G的就绪队列,以及分配堆内存所需的地址空间等
这些在运行main.main前就在runtime.main中(程序启动时)创建好,所以并发执行时就可以避免冲突

P的本地队列上限默认最多 GOMAXPROCS = 256 个,如果想要更改队列长度限制,使用 runtime.GOMAXPROCS(n) 调整

M

M 是处理器,绑定一个具体的OS线程(内核线程),Goroutine 运行的上下文在这里被调度并执行,所以也是 Goroutine 执行的上下文
管理 Goroutine 的运行状态、切换执行上下文
Go 运行时系统会根据机器硬件和条件动态地分配这些处理器,以确保 Goroutine 能够高效地并发运行

一个 M 最多有一个空闲的 P,有一个M阻塞,会创建或者唤醒一个新的M;若有空闲,则会回收或睡眠此M。
全局队列作为一个候选队列,可以同时为不同的 P 提供 Goroutine,从而使 Goroutine 尽快找到执行线程(M)
如果所有的 P 的本地队列都已满,并且全局队列也已满,Go 运行时系统将通过动态增加 M 的数量来解决压力
以尽快地使 Goroutine 开始运行,但OS是否愿意加M,则需要根据系统负载来定。

在默认情况下,全局队列的大小是默认 P 的数量的系数,最小值为 4,最大值为 32768

OS分配到当前Go程序的内核线程数

使用 runtime.NumCPU() 查询M数量,返回当前系统可用的逻辑处理器数量

返回值可能会因为不同的操作系统和系统配置而有所不同
有些操作系统可能会在系统负载高峰期动态增加或减少 M 的数量,以适应不同的负载需求
只会返回运行时系统认为当前可用的逻辑处理器数量,而不是一成不变的固定值

当所有 P 的本地队列都已满,且全局队列也满时,有新的Goroutine就绪

  • Go 运行时系统会请求操作系统分配更多线程,以进一步提高系统并发处理的能力,启动一个新线程,即新的 M (machine)
  • 新的 M 将从全局队列中拿走一个等待 Goroutine 并开始运行它
  • 新的 M 将在全局队列和所有本地队列之间轮询,直到所有队列都变得空闲或有 Goroutine 准备好运行,这将减少因 Goroutine 等待执行带来的延迟

GMP 特点

Go 语言的并发性能和可伸缩性得到了最大化的利用。
当 CPU 资源充足时,它可以在 Goroutine 和 P 之间平衡负载,并在适当的时候调度 Goroutine 到合适的 M 上以保证运行效率

Go 协程调度为什么优于线程

多进程/多线程问题

进程/线程数量越多,切换成本越大
多进程/多线程的壁垒:高内存占用,高CPU调度切换
同步竞争,如锁等

协程如何设计

N:1 : 无法利用多个CPU,出现阻塞瓶颈
​1:1 :和多线程、多进程无区别,切换协程成本代价昂贵
​M:N :能够利用多核,过度依赖协程调度器的优化和算法

如何高效

复用线程

避免频繁的创建、销毁线程,而是对线程的复用

Work stealing机制 (work偷窃)

当本线程的P队列中没有G可用并且全局队列为空时,会主动去其他线程的P队列中获取,避免线程的销毁

handle off 机制

当本线程的G运行阻塞时,会释放绑定的P队列,把P队列转移到其他空闲的线程上去

利用并行

GOMAXPROCS设置P的数量,最多有GOMAXPROCS个线程分布在CPU上运行

抢占

一个Goroutine 最多占用CPU 10ms 就会交给其他协程,防止其被饿死
Go 语言的抢占是基于协作式调度的,而切换的主动权在 Goroutine 执行上

  • 通过代码的设计来主动让 Goroutine 放弃控制权,以便让其它 Goroutine 获得执行时间片
    使用 runtime.Gosched() 主动让当前 Goroutine 放弃 CPU 控制权,使当前 Goroutine 立即进入就绪状态,并重新排队等待下一次调度
  • 内部编写超时限制的代码来防止 Goroutine 长时间执行

Go如何调整协程优先级?
在 Go 语言中,所有 Goroutine 都有相同的默认优先级,不能直接通过代码来调整 Goroutine 的优先级
这个是不是一个协程的缺点?我觉着是

全局G队列

当M执行work stealing 机制时,无法从其他P中获取G,就会从全局队列中获取

总结

G是买家,M是卖家,M根据最近的行情,动态调整,也可以去抢其他M的活
G呢,买的东西也不知道是哪个M操办的,G之间是公平的

参考文档

https://juejin.cn/post/7119307307728994335

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

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

相关文章

ChatGPT使用技巧整理

目录 1. 让ChatGPT扮演专家角色2. 告诉ChatGPT你的身份3. 限制ChatGPT的回答长度4. 让ChatGPT一步步思考5. 明确你的要求和目的6. 提供充分的背景信息7. 始终结构化思考你的prompt1. 让ChatGPT扮演专家角色 当你们讨论的是市场营销问题时,你可以要求ChatGPT扮演一个具有20年从…

[golang gui]fyne框架代码示例

1、下载GO Go语言中文网 golang安装包 - 阿里镜像站(镜像站使用方法:查找最新非rc版本的golang安装包) golang安装包 - 中科大镜像站 go二进制文件下载 - 南京大学开源镜像站 Go语言官网(Google中国) Go语言官网(Go团队) 截至目前(2023年9月17日&#x…

面试题库(一):数据结构和算法

链表 链表,常见的面试题有写一个链表中删除一个节点的算法、单链表倒转、两个链表找相交的部分,这个一般必须得完全无误的情况下写出来;给出两个链表的头结点,找出这两个链表的交点。java 中数组和链表的区别,各自优势 如何设计拥有高效的随机读取能力的的链表(跳表) 设…

【字符串】后缀数组

参考文章&#xff1a; 数据结构 —— 字符串&#xff1a;后缀数组_Jetiaime的博客-CSDN博客&#xff08;算法代码&#xff09; 后缀数组_KonjakLAF的博客-CSDN博客&#xff08;应用例题&#xff09; 板子&#xff1a; #include<bits/stdc.h> using namespace std; ty…

【数据分享】2005-2022年全国民航机场客货吞吐量和起降架次数据

机场是一个城市对外联系的重要渠道&#xff0c;机场的旅客吞吐量和货物吞吐量是体现一个城市对外联系程度的重要指标。 本次我们给大家分享的是2005-2022年我国民航机场的旅客吞吐量、货邮吞吐量、起降架次数据。数据格式为Excel和Shp两种格式。数据坐标为WGS1984。原始数据来…

MySQL常考知识点

MySQL常考知识点 索引的基本原理索引设计的原则事务的基本特性和隔离级别什么是MVCC简述MyISAM和InnoDB的区别Explain语句结果中各个字段分表表示什么索引覆盖是什么最左前缀原则是什么B树和B树的区别&#xff0c;为什么Mysql使⽤B树Mysql锁有哪些&#xff0c;如何理解Mysql慢查…

腾讯面试题:无网络环境,如何部署Docker镜像?

亲爱的小伙伴们&#xff0c;大家好&#xff01;我是小米&#xff0c;很高兴再次和大家见面。今天&#xff0c;我要和大家聊聊一个特别有趣的话题——腾讯面试题&#xff1a;无网络环境&#xff0c;如何部署Docker镜像&#xff1f;这可是一个技术含量颇高的问题哦&#xff01;废…

nodejs 如何在npm发布自己的包 <记录>

一、包结构 必要结构&#xff1a; 一个包对应一个文件夹&#xff08;文件夹名不是包名&#xff0c;但最好与包名保持一致&#xff0c;包名以package.json中的name为主&#xff09;包的入口文件index.js包的配置文件package.json包的说明文档README.md 二、需要说明的文件 1.配…

PyTorch实战:卷积神经网络详解+Python实现卷积神经网络Cifar10彩色图片分类

目录 前言 一、卷积神经网络概述 二、卷积神经网络特点 卷积运算 单通道&#xff0c;二维卷积运算示例 单通道&#xff0c;二维&#xff0c;带偏置的卷积示例 带填充的单通道&#xff0c;二维卷积运算示例 Valid卷积 Same卷积 多通道卷积计算 1.局部感知域 2.参数共…

软件测试的理论基础1

软件的生命周期 可行性研究和计划&#xff08;立项&#xff09; 需求分析 概要设计&#xff08;测试计划&#xff09; 详细设计&#xff08;测试方案&#xff09; 实现&#xff08;开发阶段&#xff1b;包含单元测试&#xff09; 组装测试&#xff08;集成测试&#xff09; 确…

【MT7628AN】IOT | MT7628AN OpenWRT开发与学习

IOT | MT7628AN OpenWRT开发与学习 时间:2023-06-21 文章目录 `IOT` | `MT7628AN` `OpenWRT`[开发与学习](https://blog.csdn.net/I_feige/article/details/132911634?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22132911634…

空间(蓝桥杯)

空间 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 小蓝准备用 256MB 的内存空间开一个数组&#xff0c;数组的每个元素都是 32 位 二进制整数&#xff0c;如果不考虑程序占用的空间和维护内存需要的辅助空间&#xff0c;…

上PICO,沉浸式观看亚运直播,参与跨国界游戏竞技

备受瞩目的杭州第19届亚运会&#xff0c;将于9月23日正式开幕。据悉&#xff0c;这也是有史以来项目最多的一届亚运会&#xff0c;除部分传统奥运项目外&#xff0c;还包含武术、藤球、板球、克柔术、柔术等亚洲特色项目&#xff0c;以及霹雳舞、电子竞技等深受年轻人喜爱的新兴…

完成flex布局与float布局

当涉及到布局时&#xff0c;Flex布局和Float布局是两种不同的方法&#xff0c;它们分别用于实现不同的布局需求。下面我将为你展示如何使用这两种方法来完成布局。 1. 使用Flex布局&#xff1a; Flex布局是一种强大的布局方法&#xff0c;特别适用于创建响应式和灵活的布局。…

Mojo编程语言是AI人工智能的新的编程语言

Mojo是Chris Lattner的创业公司Modular开发的一种新的编程语言&#xff0c;旨在统一AI基建和异构计算。Mojo被认为是Python的超集&#xff0c;兼容Python生态&#xff0c;但添加了系统编程和编译期优化的特性&#xff0c;以提高性能和部署效率。Mojo基于MLIR&#xff0c;可以支…

debian终端快捷键设置

为了方便使用图形化debian&#xff0c;快捷调出shell终端是提升工作学习效率的最重要的一步。 1.首先点击右上角&#xff0c;选择设置 2.点击键盘&#xff0c;选择快捷键&#xff0c;并创建自定义快捷键 3.点击添加快捷键 4.根据图中提示创建快捷键 Name: Terminal Command…

promise回顾和总结(温故知新)

文章目录 promise回顾和总结&#xff08;温故知新&#xff09;1.promise语法 promise回顾和总结&#xff08;温故知新&#xff09; 参考: https://juejin.cn/post/6844903604009041928 1.promise语法 Promise编程的核心思想是如果数据就绪(promised)&#xff0c;那么(then)做点…

Android Jetpack Compose之UI的重组和自动刷新

1.概述 我们都知道&#xff0c;在传统的View中&#xff0c;若要改变UI&#xff0c;需要我们修改View的私有属性&#xff0c;比如要修改一个TextView的文字&#xff0c;我们需要通过它的setText(“xxx”)方法去修改。而Compose 则是通过重组来刷新UI。在之前的状态管理的文章中…

MyBatis的动态 SQL、代理机制与多级缓存

MyBatis的动态 SQL、代理机制与多级缓存 前言一、动态 SQL二、代理机制三、多级缓存最后 前言 MyBatis 是一个开源的 Java 持久层框架&#xff0c;它通过 XML 或注解的方式将 SQL 语句与 Java 对象进行映射。相比于传统的 JDBC 操作数据库&#xff0c;MyBatis 简化了很多重复的…

uni-app获取地理位置

在uni-app中&#xff0c;可以通过uni.getLocation()方法获取地理位置。具体步骤如下&#xff1a; 在uni-app项目中的manifest.json文件中&#xff0c;添加需要获取地理位置的权限&#xff1a; {"mp-weixin": {"appid": "...","permission…