- 为什么用户实现协程
- POSIX线程模型累赘
- os调度对go模型不合理
- go gc需要内存处理一致状态(所有线程停止), os调度时,因gc时间不确定,期间大量线程停止工作
- go调度器知道什么时候内存处于一致性状态(只需正在核上运行线程)
- 本质
- 调度方式(线程模型)
- N:1 # N个用户空间线程运行在1个内核空间线程
- 1:1
- POSIX(pthread), java
- 利用多核
- 上下文切换慢,每次调度都在用户态和内核态间切换
- M:N
- 任意内核模型管理任意goroutine
- 调度复杂性大
- go
- M(machine)代表内核线程
- G(goroutine)有自己的栈,程序计数器,调度信息(如正阻塞的channel)
- P(processor)调度上下文, $GOMAXPROCS设置数量
- P中有G队列(runqueue, 队尾添加新G)
- 当前运行一个G, 到调度点时,队列弹出另一个G
- P周期检查全局G队列防止其中G饿死
- P运行完,全局G队列拉取G
- P运行完,全局G队列空,从其它P拉取一半G
- P运行在M, M阻塞时P移到其它M, 阻塞M中保留阻塞的G
- 调度器创建足够多M跑P
- 阻塞M中G的syscall返回, M尝试偷一个P
- 没得到P时, 它的G加入全局G队列, M进线池睡眠