您当前所在位置:首页攻略Go runtime 调度器精讲:异步抢占

Go runtime 调度器精讲:异步抢占

更新:2024-09-17 10:14:26编辑:游戏资讯归类:攻略

原创文章,欢迎转载,转载请注明出处,谢谢。


前面介绍了运行时间过长和系统调用引起的抢占,它们都属于协作式抢占。本讲会介绍基于信号的真抢占式调度。

在介绍真抢占式调度之前看下 Go 的两种抢占式调度器:

抢占式调度器 - Go 1.2 至今

  • 基于协作的抢占式调度器 - Go 1.2 - Go 1.13
    改进:通过编译器在函数调用时插入 抢占检查 指令,在函数调用时检查当前 Goroutine 是否发起了抢占请求,实现基于协作的抢占式调度。
    缺陷:Goroutine 可能会因为垃圾收集和循环长时间占用资源导致程序暂停。
  • 基于信号的抢占式调度器 - Go 1.14 至今
    改进:实现了基于信号的 真抢占式调度
    缺陷 1:垃圾收集在扫描栈时会触发抢占式调度。
    缺陷 2:抢占的时间点不够多,不能覆盖所有边缘情况。

注:该段文字来源于 抢占式调度器

协作式抢占是通过在函数调用时插入 抢占检查 来实现抢占的,这种抢占的问题在于,如果 goroutine 中没有函数调用,那就没有办法插入 抢占检查 ,导致无法抢占。我们看 Go runtime 调度器精讲(七):案例分析 的示例:

//go:nosplit
func gpm() {
  var x int
  for {
    x++
  }
}

func main() {
  var x int
  threads := runtime.GOMAXPROCS(0)
  for i := 0; i < threads; i++ {
    go gpm()
  }

  time.Sleep(1 * time.Second)
  fmt.Println("x = ", x)
}

禁用异步抢占:

# GODEBUG=asyncpreemptoff=1 go run main.go

程序会卡死。这是因为在 gpm 前插入 //go:nosplit 会禁止函数栈扩张,协作式抢占不能在函数栈调用前插入 抢占检查 ,导致这个 goroutine 没办法被抢占。

而基于信号的真抢占式调度可以改善这个问题。

以上就是电脑114游戏给大家带来的关于Go runtime 调度器精讲:异步抢占全部内容,更多攻略请关注电脑114游戏。

电脑114游戏-好玩游戏攻略集合版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

归龙潮开荒期阵容选择攻略 牛仔超级忙 1.1.2