乐趣区

关于golang:动图图解GMP模型里为什么要有P背后的原因让人暖心

文章继续更新,能够微信搜一搜「golang 小白成长记」第一工夫浏览,回复【教程】获 golang 收费视频教程。本文曾经收录在 GitHub https://github.com/xiaobaiTec… , 有大厂面试残缺考点和成长路线,欢送 Star。

GM 模型是什么

Go 1.1版本之前,其实用的就是 GM 模型。

  • G,协程。通常在代码里用 go 关键字执行一个办法,那么就等于起了一个G
  • M内核 线程,操作系统内核其实看不见 GP,只晓得本人在执行一个线程。GP 都是在 用户层 上的实现。

除了 GM以外,还有一个 全局协程队列 ,这个全局队列里放的是多个处于 可运行状态 GM如果想要获取 G,就须要拜访一个 全局队列 。同时,内核线程M 是能够同时存在多个的,因而拜访时还须要思考 并发 平安问题。因而这个全局队列有一把 全局的大锁,每次拜访都须要去获取这把大锁。

并发量小的时候还好,当并发量大了,这把大锁,就成为了 性能瓶颈

GMP 模型是什么

基于 没有什么是加一个中间层不能解决的 思路,golang在原有的 GM 模型的根底上退出了一个调度器 P,能够简略了解为是在GM两头加了个中间层。

于是就有了当初的 GMP 模型里。

  • P 的退出,还带来了一个 本地协程队列 ,跟后面提到的 全局队列 相似,也是用于寄存 G,想要获取期待运行的G,会 优先 从本地队列里拿,拜访本地队列无需加锁。而全局协程队列仍然是存在的,然而性能被弱化,不到 万不得已 是不会去全局队列里拿 G 的。
  • GM模型里 M 想要运行 G,间接去全局队列里拿就行了;GMP 模型里,M想要运行G,就得先获取P,而后从 P 的本地队列获取 G

  • 新建 G 时,新 G 会优先退出到 P 的本地队列;如果本地队列满了,则会把本地队列中一半的 G 挪动到全局队列。
  • P 的本地队列为空时,就从全局队列里去取。

  • 如果全局队列为空时,M 会从其余 P 的本地队列 偷(stealing)一半 G 放到本人 P 的本地队列。

  • M 运行 GG 执行之后,M 会从 P 获取下一个 G,一直反复上来。

为什么 P 的逻辑不间接加在 M 上

次要还是因为 M 其实是 内核 线程,内核只晓得本人在跑线程,而 golang 的运行时(包含调度,垃圾回收等)其实都是 用户空间 里的逻辑。操作系统内核哪里还晓得,也不须要晓得用户空间的 golang 利用原来还有那么多花花肠子。这所有逻辑交给应用层本人去做就好,毕竟改内核线程的逻辑也不适合啊。

如果文章对你有帮忙,看下文章底部右下角,做点正能量的事件(点两下 )反对一下。( 疯狂暗示,托付托付,这对我真的很重要!

我是小白,咱们下期见。

参考资料

[1]《Golang 调度器 GMP 原理与调度全剖析》——Aceld :https://learnku.com/articles/…

[2]《GMP 模型为什么要有 P》——煎鱼 :https://mp.weixin.qq.com/s/an…

[3]《深度解密 Go 语言之 Scheduler》——qcrao :https://qcrao.com/2019/09/02/…

文章举荐:

  • i/o timeout,心愿你不要踩到这个 net/http 包的坑
  • 妙啊! 程序猿的第一本互联网黑话指南
  • 程序员防猝死指南
  • 我感觉,我可能要拿图灵奖了。。。
  • 给大家争脸了,用了三年 golang,我还是没答对这道内存透露题
  • 硬核!漫画图解 HTTP 知识点 + 面试题
  • TCP 粘包 数据包:我只是犯了每个数据包都会犯的错 | 硬核图解
  • 硬核图解!30 张图带你搞懂!路由器,集线器,交换机,网桥,光猫有啥区别?
别说了,关注公众号:【golang 小白成长记】,一起在常识的陆地里呛水吧

关注公众号:【golang 小白成长记】

退出移动版