goroutine和GPM调度
目录
一、Go 语言的协程 goroutine
1. goroutine概念
2. goroutine特点
二、m:n调度技术
三、goroutine 调度器的实现
1. 被废弃的调度器
2.新调度器GPM设计思想
3.P和M的数量和创建
数量
创建
4.调度器的设计策略
线程复用
利用并行
抢占
全局 G 队列
5.GPM调度流程
6.调度器的生命周期
一、Go 语言的协程 goroutine
1. goroutine概念
goroutine 来自协程的概念,让一组可复用的函数运行在一组线程之上;
即使有协程阻塞,该线程的其他协程也可以被 runtime 调度,转移到其他可运行的线程上;
2. goroutine特点
占用内存更小(只占几 KB,可伸缩的,runtime会自动为goroutine分配更多内存);
调度更灵活 (runtime 调度);
二、m:n调度技术
m:n调度的技术,m个goroutine(G)调度到n个OS线程(M)上运行;
一对一和一对多的缺点;
三、goroutine 调度器的实现
1. 被废弃的调度器
2012年重新设计之前的调度器,只有GM;
特征:
1)M 想要执行、放回 G ,都必须访问全局 G 队列;
2)M 有多个,即多线程访问同一资源(即G队列)需要加锁进行保证互斥 / 同步。
老调度器有几个缺点:
1)激烈的锁竞争;
2)M 转移 G 会造成延迟和额外的系统负载;
比如当 G 中包含创建新协程的时候,M 创建了 G’;为了执行 G,需要把 G’交给 M’,也造成了很差的局部性,因为 G’和 G 是相关的,最好放在 M 上执行,而不是其他 M’;
3)系统调用 (CPU 在 M 之间的切换) 导致频繁的线程阻塞和取消阻塞操作增加了系统开销;
2.新调度器GPM设计思想
GPM是Go语言运行时层面(用户态)的实现,是go语言自己实现的一套调度系统,区别于操作系统调度OS线程(内核态)。
1)G:Goroutine,协程;
包含goroutine信息和与P的绑定信息;
2)P:Processor,调度器;
所有的 P 都在程序启动时创建,并保存在数组中,最多有 GOMAXPROCS(可配置) 个;
管理和调度一组goroutine队列,当自己的队列消费完了去全局队列里取,全局队列里消费完了会去其他P队列里取;
2)M:Machine,线程映射;
Go运行时(runtime)对操作系统内核线程的虚拟, M与内核线程一般是一一映射的关系;
线程想运行任务就得获取 P,从 P 的本地队列获取 G;
4)GQ:全局队列(Global Queue);
5)LQ:P 的本地队列;
存的数量有限,不超过 256 个;
满:新建 G’时,G’优先加入到 P 本地队列,如果队列已满,则把队列中前一半的 G和新创建的G移动到全局队列;
空:P 队列为空时,M 尝试从全局队列拿一批 G 【负载均衡,min(全局队列长度/P的数量 + 1, 全局队列长度/2)】放到 P 本地队列,或从其他 P 本地队列后一半放到自己 的P 本地队列;
协程和线程是通过P结合起来的(G - P -M), 线程想运行任务就得获取 P,从 P 的本地队列获取 G;
Goroutine 调度器和 OS 调度器是通过 M 结合起来的(goroutine调度器 - M - OS调度器);
3.P和M的数量和创建
数量
1)P 的数量:
由GOMAXPROCS决定,可配置;
这意味着在程序执行的任意时刻都只有 $GOMAXPROCS 个 goroutine 在同时运行;
2)M 的数量:
go 语言限制:go 程序启动时,会设置 M 的最大数量,默认 10000,但是内核很难支持这么多的线程数;
SetMaxThreads 函数,可设置 M 的最大数量;
一个 M 阻塞了,会创建新的 M;
3)M与P数量的关系:
M 与 P 的数量没有绝对关系,一个 M 阻塞,P 就会去创建或者切换另一个 M;
即使 P 的默认数量是 1,也有可能会创建很多个 M 出来;
创建
1)P 何时创建:
在确定了 P 的最大数量 n 后,运行时系统会根据这个数量创建 n 个 P。
2)M 何时创建:
没有足够的 M 来关联 P 并运行其中的可运行的 G时,会创建新的M;
比如所有的 M 此时都阻塞住了,而 P 中还有很多就绪任务,就会去寻找空闲的 M,而没有空闲的,就会去创建新的 M;
4.调度器的设计策略
线程复用
work stealing 机制
当本线程无可运行的 G 时,尝试从其他线程绑定的 P 偷取 G,而不是销毁线程。
hand off 机制
当本线程因为 G 进行系统调用阻塞时,线程释放绑定的 P,把 P 转移给其他空闲的线程执行。
利用并行
GOMAXPROCS 设置 P 的数量,最多有 GOMAXPROCS 个线程分布在多个 CPU 上同时运行。
抢占
在 coroutine 中要等待一个协程主动让出 CPU 才执行下一个协程;
在 Go 中,一个 goroutine 最多占用 CPU 10ms,防止其他 goroutine 被饿死;
全局 G 队列
在新的调度器中依然有全局 G 队列,但功能已经被弱化了;
当 M 执行 work stealing 从其他 P 偷不到 G 时,它可以从全局 G 队列获取 G;
5.GPM调度流程
从上图我们可以分析出几个结论:
1)我们通过 go func () 来创建一个 goroutine;
2)有两种存储 G 的队列,一个是局部调度器 P 的本地队列、一个是全局 G 队列;新创建的 G 会先保存在 P 的本地队列中,如果 P 的本地队列已经满了就会保存在全局的队列中;
3)G 只能运行在 M 中,一个 M 必须持有一个 P,M 与 P 是 1:1 的关系;M 会从 P 的本地队列弹出一个 G 来执行,如果 P 的本地队列为空,就会想其他的 MP 组合偷取一个可执行的 G;
4) 一个 M 调度 G 执行的过程是一个循环机制;
5)当 M 执行某一个 G 时候如果发生了 syscall 或则其余阻塞操作,M 会阻塞;如果当前有一些 G 在执行,runtime 会把这个线程 M 从 P 中摘除 (detach);然后再创建一个新的操作系统的线程 (如果有空闲的线程可用就复用空闲线程) 来服务于这个 P;
6)当 M 系统调用结束时候,这个 G 会尝试获取一个空闲的 P 执行,并放入到这个 P 的本地队列;如果获取不到 P,那么这个线程 M 变成休眠状态, 加入到空闲线程中,然后这个 G 会被放入全局队列中。
6.调度器的生命周期
goroutine和GPM调度相关推荐
- go进阶(1) -深入浅出goroutine并发运行调度机制
并发指的是同时进行多个任务的程序,Web处理请求,读写处理操作,I/O操作都可以充分利用并发增长处理速度,随着网络的普及,并发操作逐渐不可或缺 一.goroutine简述 在Golang中一个goro ...
- Go GPM 调度器介绍
Go GPM 调度器介绍 1 简介 这几天在学习Go的GPM机制,于是就整理了一下收集的资料分享给大家,文章末尾有原文链接.主要介绍了Go在运行时调度器的基本实现逻辑和演变过程. 2 什么是G ...
- 都说 Go 可以开启成千上万的 Goroutine,那调度器是怎么处理核上任务分配的?
转载地址:https://mp.weixin.qq.com/s/_By9rjPgb8zqIpVrsJrToQ Illustration created for "A Journey With ...
- Go语言的GPM调度器是什么?
博客主页:
- Go 开源说第十八期预告:基于 Reactor 模式开发网络服务——gnet
点击蓝字 关注我们 写在前面 GoCN开源说是GoCN推出的一档分享Go开源好项目的直播栏目,通过开源说希望能够帮助到开源作者们实现以下目标: 第一是去推广他们的开源项目 第二说说背后的设计原理和理念 ...
- go语言之行--golang核武器goroutine调度原理、channel详解
一.goroutine简介 goroutine是go语言中最为NB的设计,也是其魅力所在,goroutine的本质是协程,是实现并行计算的核心.goroutine使用方式非常的简单,只需使用go关键字 ...
- goroutine调度详解,以及进程、线程、协程区别
转载地址:https://blog.csdn.net/Arlingtonroad/article/details/106952053?utm_medium=distribute.pc_relevant ...
- go 获取内核数_Go的GPM多线程调度
现在前面:希望大家在做知识分享时,多验证自己内容的正确性.在学习GPM模型过程中,同一个概念看到了不同的解释.我查阅了一些资料选择了最可信的.由于我也没有阅读Go的调度源码,不能100%保证正确性,如 ...
- Goroutine并发调度模型深度解析之手撸一个协程池
Goroutine & Scheduler Goroutine,Go语言基于并发(并行)编程给出的自家的解决方案.goroutine是什么?通常goroutine会被当做coroutine(协 ...
最新文章
- leetcode-142 环形链表II
- 《Elixir in Action》书评及作者问答录
- 探索7.x, 全面解析Activity启动框架 (1)
- 【翻译】卡通图解DNS,你的信息怎么被泄露的?
- Android input 子设备adb 调试命令
- ps cs3怎样能保存html,ps cs3用消失点清理杂物方法介绍
- 系统工程理论与实践投稿经验_钱学森的系统工程 | 如是读
- 时间序列-N-CNN-LSTM
- 前端框架 Angular 11.0.0 正式发布,已经放弃 IE 9 、10
- linux清除占用端口,Linux中解除端口占用的方法
- 3. Builder(建造者)
- Matlab中镜头畸变矫正
- Unity PlayerSetting设置
- 图像处理算法之图像暗角特效
- 10分钟从零搭建QQ机器人,实现自动回复、推送等功能
- 为什么中文不能用来编程呢?难道中文比英语差?看完长见识了
- 搞笑的各大银行的简称
- 高云FPGA实现驱动MIPI LCD屏
- css选择器优先级深入理解
- 1U和2U服务器应如何正确选择?各有什么优缺点?