GMP
为什么会出现协程
- 进程和线程
- 资源占用高
- CPU切换成本高
- 多线程编程需要考虑资源互斥与通信等资源共享问题,编程复杂
- 协程
- co-routine,将线程划分为用户空间和内核空间,用户空间的操作单位即称为协程
- 与线程的关系
- 1:1
- 一一绑定,与线程没有太大区别了
- N:1
- 一个线程对应多个协程的调度,缺点是不支持多核
- N:M
- 多对多,更好的利用多核优势,缺点依赖调度器,性能和调度器实现密切相关
- 1:1
go中的协程
- 轻量级,内存占用只有4k
- 用户态切换成本低,调度灵活
GMP的调度
- 简介
- G
- 协程
- M
- 工作线程
- P
- 处理器
- G
- 调度
- 1. 程序启动时,会先创建M0,每个M0也会同时创建一个g0与它一一对应,用于调度其他协程
- 2.g0进行初始化等操作,创建main协程g1,将g1挂到当前p上的本地队列中,g0完成初始化等操作后,将控制权交还给线程M,g1和M进行绑定,开始执行g1操作
- 3.当g1执行结束后,调度器会继续取出队列中的数据进行执行
- 4.当本地为空时,将去全局队列取出一些G放到自己的本地队列中进行执行(min(gq/maxprocnum+1, gq/2))
- 5.如果全局队列中也为空,则会去其他p偷取一半的g存放到自己的本地队列中进行执行
- 6.后续如果该g中继续创建g,则优先放入自己的本地队列,如果满了则将本地队列的前一半加上当前g进行顺序打乱,然后加入全局队列等待调度
- 7.如果此时g发生阻塞了,那将会与M进行绑定,然后P唤醒休眠M列表,然后与一个空闲的M进行绑定,如果没有M将会创建一个M与之绑定继续调度执行g