day7 golang GMP
2023-04-06 20:44 dribs 阅读(21) 评论(0) 编辑 收藏 举报大名鼎鼎的GMP模型 需要自行学习的知识:进程、线程、协程、多线程、线程池、io多路复用,内核态用户态,,同步阻塞异步非阻塞等等相关知识
代码是在线程中运行的,协程也是,所以当协程阻塞的时候该线程也阻塞了,其他任务就无法调度了,该线程就死了。
如何解决,那就需要让协程自由的在线程中移动,当阻塞的时候把他扔一边,把其他协程绑定到该线程上让他继续干活。
等刚才阻塞的任务又活过来的时候,在把这个协程任务和线程绑定起来,继续干活。
理解了上面这些就可以简单看GMP模型了
G:goroutine 任务函数包装成go协程,也就是go协程,他存储了协程的执行栈信息、状态、任务函数等,初始栈大小2-4K
M:machine Thread,对系统线程抽象封装,所有代码最终都要在系统线程上运行
P:Processor 虚拟处理器,默认为cpu核心数,p的数量决定着最大可并行的G的数量;P有自己的队列长度LRQ长度256,这里放的是待执行的G;M和P绑定在一起,这样P队列中的G才能真正的在线程上执行
下面以topgoer.com里的图为例解释
1、通过go 关键字创建goroutine,把创建好的G1-Gn放到P的本地队列,如果LRQ满了超过256,则放到GRQ全局队列
2、P1和M1 绑定,M1从P1的LRQ中请求G,如果没有则从GRQ中请求,如果还没有就偷其他P中的G到自己的LRQ中,最后在M1上执行,执行完解绑,继续绑定拿G执行。
3、如果进入chanel 互斥锁阻塞,解绑,继续拿G绑定执行,如果g1被唤醒就把g1的任务放入唤醒的自己的LRQ中,如果队列满就把g1和LRQ中的一半仍到GRQ中
4、如果遇到同步阻塞,g1和m1都阻塞,那就把m1和p1解绑,p1在从休眠里面拿一个m和自己绑定(没有就创建),获取p1里的其他g继续在m上跑;如果m1阻塞结束,优先和p1绑定,如果没闲着的p,g1进GRQ,m1进休眠队列