golang中的add和done执行先后顺序

//代码A
package main

import (
	"fmt"
	"sync"
)
func main() {
  var wg sync.WaitGroup
  fmt.Println(1)
  go wg.Done()
  wg.Add(1)
  wg.Wait()
}
//代码B
package main

import (
	"fmt"
	"sync"
)
func main() {
  var wg sync.WaitGroup
  fmt.Println(1)
  wg.Done()
  go wg.Add(1)
  wg.Wait()
}

//代码C
package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup

	wg.Add(3)
	for i := 0; i < 3; i++ {
		go func(i int) {
			fmt.Println(i)
			wg.Done()
		}(i)
	}
	wg.Wait()
}

//代码D
package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup

	for i := 0; i < 3; i++ {
		go func(i int) {
			fmt.Println(i)
			wg.Done()
		}(i)
	}
	wg.Add(3)
	wg.Wait()
}

谁能给我解释一下done和add的执行时机?go之后执行先后顺序应该是不确定的,为什么ACD的都会稳定先执行add后执行done,代码B稳定出问题

#悬赏#
全部评论
首先要知道的是:报错的原因wg.Done()源码是wg.Add(-1),最终导致wg中任务数小于0而报错。 C是先加任务数后减任务数,所以不会报错;B是先减后加,所以必定报错;A和D中wg.Done()和wg.Add(1)存在竞争关系,而我们常规测试不报错的原因是创建新协程的速度肯定不及当前协程运行的速度,所以主协程的wg.Add(1)大概率会比子协程的wg.Done()先执行。如果在wg.Add(1)前加入time.Sleep(time.Second),则一定会保证。 PS:我怀疑你自己都没测试,wg都没初始化。。。
1 回复 分享
发布于 2023-11-16 16:55 北京

相关推荐

10-24 13:36
门头沟学院 Java
Zzzzoooo:更新:今天下午有hr联系我去不去客户端,拒了
点赞 评论 收藏
分享
无情咸鱼王的秋招日记之薛定谔的Offer:好拒信,偷了,希望有机会用到
点赞 评论 收藏
分享
点赞 1 评论
分享
牛客网
牛客企业服务