栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

聊一聊Go中的GMP调度模型

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

聊一聊Go中的GMP调度模型

调度模型的由来

早期操作系统是单进程的,那么执行进程只能是顺序执行的

  • 顺序执行,效率比较低
  • 当前进程的阻塞会带来CPU浪费,因为CPU没办法处理后面待处理的进程

后来出现了多进程操作系统,多进程处理下,会涉及到基于CPU调度器对进程分配时间片,宏观上三个进程在并发,实际还是顺序执行,这么看来,解决了进程阻塞带来对CPU浪费

但是这种方式会带来进程切换成本(进程切换涉及到拷贝复制)的浪费。


当进程数量越多,切换成本也就越浪费,CPU的一部分浪费在了切换上。

除此之外,进程和线程占用内存是很大的,进程虚拟内存占用可能是GB级别的,线程是MB级别的。

总的来说,高消耗CPU和高内存占用都是需要解决的问题。

怎么解决呢?

线程分为用户空间和内核空间

线程也会涉及用户态和内核态之间的切换,如果把线程一分为二,即用户线程和内核线程,用户线程负责业务上的处理,内核线程负责操作系统层面的处理。


我们把用户线程称为协程,内核线程还称为线程。为了进一步提高效率,我们通过协程调度器来为内核线程绑定多个协程。

协程调度器通过轮询的方式与协程配合

这看起来是1:N的关系,但是这样有个弊端:如果有一个协程阻塞了,考虑到轮询的机制,那就说真阻塞了,所以一个线程是不够的。

所以进一步演化为一种M:N的关系

什么是GMP?

  • G是Goroutine的缩写,相当于操作系统的进程控制块(process control block)。它包含:函数执行的指令和参数,任务对象,线程上下文切换,字段保护,和字段的寄存器。
  • M是一个线程,每个M都有一个线程的栈。如果没有给线程的栈分配内存,操作系统会给线程的栈分配默认的内存。
  • P(处理器,Processor)是一个抽象的概念,不是物理上的CPU。当一个P有任务,需要创建或者唤醒一个系统线程去处理它队列中的任务。

线程是运行goroutine的实体,调度器的功能是把可运行的goroutine分配到工作线程上。

  • 全局队列(Global Queue):存放等待运行的G。
  • P的本地队列:同全局队列类似,存放的也是等待运行的G,存的数量有限,不超过256个。新建G’时,G’优先加入到P的本地队列,如果队列满了,则会把本地队列中一半的G移动到全局队列。
  • P列表:所有的P都在程序启动时创建,并保存在数组中,最多有GOMAXPROCS(可配置)个。
  • M:线程想运行任务就得获取P,从P的本地队列获取G,P队列为空时,M也会尝试从全局队列拿一批G放到P的本地队列,或从其他P的本地队列偷一半放到自己P的本地队列。

M运行G,G执行之后,M会从P获取下一个G,不断重复下去。

Goroutine调度器,即Processor,它是和OS调度器是通过M结合起来的,每个M都代表了1个内核线程,OS调度器负责把内核线程分配到CPU的核上执行。

参考资料

https://www.kancloud.cn/aceld/golang

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/991611.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号