1、什么是协程?
对于进程、线程,都是有内核进行调度,有CPU时间片的概念,进行抢占式调度。协程,又称微线程,纤程。英文名Coroutine。协程的调用有点类似子程序,如程序A调用了子程序B,子程序B调用了子程序C,当子程序C结束了返回子程序B继续执行之后的逻辑,当子程序B运行结束了返回程序A,直到程序A运行结束。但是和子程序相比,协程有挂起的概念,协程可以挂起跳转执行其他协程,合适的时机再跳转回来。
2、线程调度原理
N:1模型,多个用户空间线程在1个内核空间线程上运行。优势是上下文切换非常快,因为这些线程都在内核态运行,但是无法利用多核系统的优点。1:1模型,1个内核空间线程运行一个用户空间线程。这种充分利用了多核系统的优势但是上下文切换非常慢,因为每一次调度都会在用户态和内核态之间切换。POSIX线程模型(pthread)就是这么做的。M:N模型,内核空间开启多个内核线程,一个内核空间线程对应多个用户空间线程。效率非常高,但是管理复杂。
3、goroutine调度原理
本质上goroutine就是协程,但是完全运行在用户态,借鉴了M:N模型。如下图
相比其他语言,golang采用了MPG模型管理协程,更加高效,但是管理非常复杂。
M:内核级线程
G:代表一个goroutine
P:Processor,处理器,用来管理和执行goroutine的。
G-M-P三者的关系与特点:
P的个数取决于设置的GOMAXPROCS,go新版本默认使用最大内核数,比如你有8核处理器,那么P的数量就是8M的数量和P不一定匹配,可以设置很多M,M和P绑定后才可运行,多余的M处于休眠状态。
P包含一个LRQ(Local Run Queue)本地运行队列,这里面保存着P需要执行的协程G的队列
除了每个P自身保存的G的队列外,调度器还拥有一个全局的G队列GRQ(Global Run Queue),这个队列存储的是所有未分配的协程G。
假设我们的主机是单核的,那么协程运行图是这样:
学习链接:https://www.cnblogs.com/secondtonone1/p/11803961.html