https://www.jianshu.com/u/bf598f8766c8 里面的多篇调度文章
https://zboya.github.io/post/go_scheduler/ 调度以这篇为准,上面的gpm调度顺序不对
正在被执行的 goroutine 发生以下情况时让出当前 goroutine 的执行权,并调度后面的 goroutine 执行:
IO 操作
Channel 阻塞
system call
运行较长时间
如果一个 goroutine 执行时间太长,scheduler 会在其 G 对象上打上一个标志( preempt),当这个 goroutine 内部发生函数调用的时候,会先主动检查这个标志,如果为 true 则会让出执行权。
main 函数里启动的 goroutine 其实是一个没有 IO 阻塞、没有 Channel 阻塞、没有 system call、没有函数调用的死循环。
也就是,它无法主动让出自己的执行权,即使已经执行很长时间,scheduler 已经标志了 preempt。
而 golang 的 GC 动作是需要所有正在运行 goroutine 都停止后进行的。因此,程序会卡在 runtime.GC() 等待所有协程退出。
评论前必须登录!
注册