协作式调度与非协作式调度
抢占式多任务处理是计算机操作系统中,一种实现多任务处理的方式,相对于协作式多任务处理
而言。协作式环境下,下一个进程被调度的前提是当前进程主动放弃
时间片;抢占式环境下,操作系统完全决定进程调度方案,操作系统可以剥夺耗时长的进程
的时间片,提供给其它进程。
Go1.12之前的协作式调度
在每个函数或方法的入口加上一段额外的代码,让runtime有机会检查是否需要执行抢占式调度。
runtime会启动一个sysmon的m(监控线程),该m无需绑定p即可运行。sysmon主要完成以下工作
- 释放闲置超过5分钟的span物理内存;
- 如果超过2分钟没有垃圾回收,强制执行;
- 将长时间未处理的netpoll结果添加到任务队列;
- 向长时间运行的G任务发出抢占调度;
- 收回因syscall长时间阻塞的P;
其中,长时间运行的g包括
1)进入系统调用阻塞超过20us
2)运行时长超过10ms
sysmon会向该g发出抢占式调度的请求。那么下一次调用函数或方法时,执行额外代码的时候可以检查抢占位是否被设置为true,是的话便主动让出cpu(看起来就像是进行了抢占),g被放入到本地队列,切换到g0,调度下一个可运行g执行。
问题
这样解决了局部的饿死问题,但是对于没有函数调用的死循环g来说,就算检查到超时运行,发送抢占请求,该g也不会主动让出cpu。