golang sync.WaitGroup deadlock死锁问题 soft lockup

golang sync.WaitGroup deadlock死锁问题 soft lockup

为什么需要sync.WaitGroup?

goroutine并发执行的时候需要一段时间,由于是串行编译运行的,有时会出现并发程序还没执行完毕,而后方的程序已经执行而导致的错误。通常的处理方式是调用time.sleep延迟并发执行时间

我们开启了1s的等待时间,但这种方法有个问题,我们并不知道并发执行的具体时间,很容易造成等待过久的时间浪费。

sync.WaitGroup的特点

WaitGroup是一个结构体,用来统计goroutine是否执行完毕,它实现了三个方法Add()、Done()、Wait()。

三个函数的主要作用:

wg.Add()设置等待组的数量(counter)。

wg.Done()当子goroutine运行结束,counter-1。

wg.Wait()等待组数量=0,主程序重新启动。counter>0时,主程序阻塞。

1
2
3
4
5
6
7
8
9
10
11
12
13
func main() {
wg.Add(10)
defer wg.Wait()
for i:=0;i<10;i++ {
go ways(i)
}
}

func ways(i int) {
defer wg.Done()
fmt.Println("启动线程:"+strconv.Itoa(i))
}

注意

等待组的数量必须和goroutine启动数量保持一直,否则会出现错误

add()数量>goroutine数量

1
2
3
4
5
6
7
8
9
10
11
12
13
func main() {
wg.Add(100)//开启一百个等待组
defer wg.Wait()
for i:=0;i<10;i++ {
go ways(i)
}
}

func ways(i int) {
defer wg.Done()
fmt.Println("启动线程:"+strconv.Itoa(i))
}

1
2
3
4
5
6
7
8
9
10
11
启动线程:0
启动线程:5
启动线程:9
启动线程:6
启动线程:3
启动线程:7
启动线程:8
启动线程:4
启动线程:1
启动线程:2
fatal error: all goroutines are asleep - deadlock!

所有goroutine都已经运行完毕,主程序还处于阻塞状态,出现死锁


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!