文章持续更新中。微信搜索“golang小白的成长故事”即可立即阅读,回复【教程】免费获取golang视频教程。本文已收录到GitHubhttps://github.com/xiaobaiTec...,有完整的大厂面试考点和成长路线,欢迎Star。什么是GM模型在Go1.1版本之前,实际使用的是GM模型。G、协程。通常,如果在代码中使用go关键字去执行一个方法,就相当于打了一个G.M,内核线程,操作系统内核其实看不到G和P,只知道自己在执行一个线程。G和P都是在用户层实现的。除了G和M之外,还有一个全局协程队列,其中包含多个处于可运行状态的G。如果M想要获取G,它需要访问一个全局队列。同时,多个内核线程M可以同时存在,因此访问时需要考虑并发安全问题。所以这个全局队列有一个全局大锁,每次访问都需要获取这个大锁。并发量小的时候还好,但是当并发量大的时候,这个大锁就成了性能瓶颈。什么是GMP模型基于没有什么是加一个中间层解决不了的思想,golang在原来GM模型的基础上增加了一个调度器P,可以简单理解为在G和G之间加了一个中间层M.所以有当前的GMP模型。P的加入也带来了一个本地协程队列,类似于上面说的全局队列。也是用来存放G的,如果要让G等待运行,会先从本地队列中取出。访问本地队列不需要加Lock。全局协程队列依然存在,只是功能被弱化了,不到万不得已不会再去全局队列拿G了。在GM模型中,如果M想运行G,可以直接从全局队列中获取;在GMP模型中,如果M要运行G,他必须先得到P,然后从P的本地队列中得到G。创建新的G时,会先将新的G加入到P的本地队列中;如果本地队列已满,则将本地队列中一半的G移至全局队列。当P的本地队列为空时,从全局队列中取。如果全局队列为空,M会从其他P的本地队列中偷取G的一半放入自己P的本地队列中。M运行G,G执行完后,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/...[3]《深度解密Go语言之Scheduler》——qcrao:https://qcrao.com/2019/09/02/...文章推荐:i/o超时,希望大家不要踩到这个网/httppackage这个坑很精彩!Programmer'sfirstInternetslangguideProgrammer'sGuidetoSuddenDeathPrevention感觉自己可能要拿图灵奖了。..惭愧大家,用了三年golang,我还是没答对这个硬核内存泄露问题!漫画图解HTTP知识点+面试题TCP粘包数据包:我刚刚犯了一个错误,每个数据包都会犯|硬核图解硬核图解!30张图告诉你如何理解!路由器、集线器、交换机、网桥和光调制解调器之间有什么区别?话不多说,关注公众号:【golang小白的成长故事】,一起在知识的海洋里窒息关注公众号:【golang小白的成长故事】
