Golang并发编程(一)-sync.WaitGroup
为什么需要sync.WaitGroup?
goroutine并发执行的时候需要一段时间,由于是串行编译运行的,有时会出现并发程序还没执行完毕,而后方的程序已经执行而导致的错误。通常的处理方式是调用time.sleep
延迟并发执行时间,如下:
func main() {
go pf()
go pf()
time.Sleep(1000 * time.Microsecond)//开启1s的延时等待
}
func pf() {
fmt.Println("并发")
fmt.Println("并发2")
}
我们开启了1s的等待时间,但这种方法有个问题,我们并不知道并发执行的具体时间,很容易造成等待过久的时间浪费。
sync.WaitGroup的特点
WaitGroup
是一个结构体,用来统计goroutine
是否执行完毕,它实现了三个方法Add()
、Done()
、Wait()
。
三个函数的主要作用:
wg.Add()
设置等待组的数量(counter)。
wg.Done()
当子goroutine运行结束,counter-1。
wg.Wait()
等待组数量=0,主程序重新启动。counter>0时,主程序阻塞。
用例
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数量
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))
}
启动线程:0
启动线程:5
启动线程:9
启动线程:6
启动线程:3
启动线程:7
启动线程:8
启动线程:4
启动线程:1
启动线程:2
fatal error: all goroutines are asleep - deadlock!
所有goroutine都已经运行完毕,主程序还处于阻塞状态,出现死锁。