go sync wait group死锁问题,请看下面代码,看起来是没有任何问题的,如果INWait .Add(1)和INWait.Done()都能执行到并且REWait .Add(1)和REWait.Done()也能执行到的情况那肯定是没有问题的.
但是如果在outCh函数中加个return那就出问题了,go run -race xxx.go执行一下,REWait .Add(1)和REWait.Done()不相等,一直阻塞,造成死锁,程序无法退出。
所以开发中waitGroup Add()后立马就延时执行defer Done()即可避免wait group 死锁问题
package main
import (
"fmt"
"sync"
"time"
)
var (
INWait = sync.WaitGroup{}//写入等待
REWait = sync.WaitGroup{}//读取等待
)
func main() {
start := time.Now().UnixNano() / 1e6 //毫秒
fmt.Println("开始时间", start)
chanNum := 100
ch := make(chan int, chanNum)
defer close(ch) //延时关闭chan
for i := 0; i < chanNum; i++ {
go inCh(ch, i) //开启N个协程写入chan
}
for i := 0; i < 100; i++ {
go outCh(ch, i) //开启N个协程读取chan
}
INWait.Wait() //等待写入管道的锁完毕
REWait.Wait() //等待读取管道的锁完毕
end := time.Now().UnixNano()/1e6 - start
fmt.Println("数据读取完毕,消耗时间毫秒", end)
}
func inCh(ch chan int, i int) {
INWait.Add(1)
//defer INWait.Done()//避免死锁
ch <- i
INWait.Done()//注销这行,在add的时候直接defer done
}
func outCh(ch chan int, i int) {
REWait.Add(1)
//defer REWait.Done()//这样就不会死锁了
val, ok := <-ch //读取到数据和值
if val%10 == 0 && ok {
if i > 80 {
//return//开启后,下面的REWait.Done()是无法运行的,出现死锁
}
fmt.Println(i, "读取到chan的数据才会执行到这里", val)
}
REWait.Done()//注销这行,在add的时候直接defer done
}
并发时候保证公共数据安全问题加锁问题注意事项:https://blog.csdn.net/qq_27517377/article/details/114824259