Go调度器如何处理goroutine阻塞的情况?
-
前置知识点: go程序中,任何对系统 API 的调用,都会被 runtime 层拦截来方便调度。
-
go一共有4种阻塞的情况,并且这些阻塞都是可以被runtime检测到的,runtime检测到阻塞时就可以进行优化处理。
- blocking syscall (for example opening a file) // 系统调用
- network input // 网络IO
- channel operations
- primitives in the sync package // 锁
4种阻塞可以分为两类:
分类1 (对应情况2,3,4): (只G阻塞,M,P可用的,要利用起来)
1.1 用户代码层面的阻塞(channel,锁), 此时M可以换上其他G继续执行。
1.2 网络阻塞 (netpoller实现G网络阻塞不会导致M被阻塞,仅阻塞G)。
分类2 (对应情况1): (G,M都被阻塞,P可用,要利用起来)
2.1 系统调用(open file)
- 参考
https://www.kancloud.cn/fruitbag/stack_of_gofuny/760985
https://povilasv.me/go-scheduler/
博主和go夜读分享者的讨论记录
TODO 这2个说法似乎有的矛盾
这里的Go调度时机和同步异步系统调用也提供了一种理解。
- 请教博客作者后,总结如下
系统调用分同步异步,对应两种处理方法。一种切换G,一种切换M,但是P不会闲着的(不养闲人)。