进程:一个在内存中运行的程序
线程:进程中的一个控制单元,一个进程至少由一个线程,也可以由多个线程,主要由CPU进行调度。
形象理解:进程就是一个生产某样产品的工厂,线程就是工厂里面的生产车间。
golang的goroutine是一个轻量化的线程。一个go主线程就可以轻轻松松起成千上万个goroutine。主要特点:
- 有独立的占空间
- 共享程序的堆空间
- 调度由用户掌控
golang的gouroutine的调度模型为MPG模型
- M:操作系统的主线程(物理线程,由CPU调度)
- P:协程执行所需要的上下文
- 协程
golang起一个goroutine很简单,只需要一个关键字go就可以轻松起一个goroutine
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GYdaqagH-1663260806647)(C:\Users\fei\AppData\Roaming\Typora\typora-user-images\image-20220916001557361.png)]
- golang起的goroutine会放在一个全局队列中,全局队列遵循先进先出的原则
- M(线程)则从全局队列中获取goroutine,每个M(线程)获取goroutine的时候,会进行加锁操作,获取goroutine完成后再释放锁,以此保证安全
- P(上下文)负责管理一个本地队列,M(线程)一次性从全局队列中获取n个goroutine,并将goroutine放到自己的一个本地队列中,n=全局队列goroutine总数/GOMAXPROCS+1
- M(线程)根据队列先进先出的原则,先执行本地队列中的goroutine,本地队列的goroutine执行完了,再到全局队列取,全局队列取完了,视情况到其他M(线程)的本地队列取。
为了保证资源调配公平,M(线程)执行G(协程)的时间超过10ms,将中断G(协程)并将这个G(协程)重新放入全局队列的队尾。
还有一种情况:goroutine下又创建goroutine
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JX7KxPEa-1663260806649)(C:\Users\fei\AppData\Roaming\Typora\typora-user-images\image-20220916004209507.png)]
- 将goroutine下创建的goroutine放到本地队列的队首位置,下一个优先执行
- 为了防止无限套娃创建goroutine,占住M(线程资源),G(协程)下创建的所有goroutine公用一个10ms时间片
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uDa2VF01-1663260806650)(C:\Users\fei\AppData\Roaming\Typora\typora-user-images\image-20220916004447135.png)]
图片转存中…(img-uDa2VF01-1663260806650)]
说明例子:假如父goroutine执行了3ms后创建了子goroutine,那子goroutine最多只能执行7ms,超过10ms,整个G(协程)就会被中断,被扔回全局队列。