文章继续更新,能够微信搜一搜「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小白成长记】