记一次关于goroutine调度的探索

记一次关于goroutine调度的探索

问题

有以下三段代码,内容大体相同,只有很小的差别。

  • 第一段
	func main() {
	runtime.GOMAXPROCS(0)
	var wg sync.WaitGroup
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func(n int) {
			print(n, " ")
			wg.Done()
		}(i)
	}
	wg.Wait()
}
  • 第二段
func main() {
	runtime.GOMAXPROCS(1)
	var wg sync.WaitGroup
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func(n int) {
			print(n, " ")
			wg.Done()
		}(i)
	}
	wg.Wait()
}
  • 第三段
func main() {
	runtime.GOMAXPROCS(1)
	var wg sync.WaitGroup
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func(n int) {
			time.Sleep(time.Second)
			print(n, " ")
			wg.Done()
		}(i)
	}
	wg.Wait()
}

其中前两段代码是无意中看到的一道go面试题中的,虽然也看到了一些对于二者输出结果的解释,但感觉还是不够清晰,于是自己做了一些尝试,并无意中发现了第三段代码。好,下面先给出这三段代码相应的输出:

  • 第一段:0到4的乱序输出
  • 第二段:4 0 1 2 3
  • 第三段:3 4 0 1 2

探索

  • 第一段的乱序输出是很好理解的,CPU是多核的,创建了多个goroutine之后,每个goroutine得到执行的顺序无法保证,所以会出现0到4的乱序输出。
  • 第二段输出的循序也是很好理解的,由于设置了单核执行,goroutine根据创建顺序依次执行,但问题在于最后创建的goroutine最先执行了。
    一顿搜索查阅之后,知道了大概原因,但总觉得不够清晰,最终找到了以下从P中获取G(go源码中表示goroutine的数据结构,关于G、P、M网上有很多大佬的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值