1.如何利用sync.WaitGroup解决死锁问题?
我的代码可以正确地打印结果,但是它会导致死锁。
我现在能想到的是:将sync.WaitGroup替换为time.Sleep。
但是我想知道如何使用sync.WaitGroup来解决死锁?
dog: 0
cat: 0
fish: 0
dog: 1
cat: 1
fish: 1
dog: 2
cat: 2
fish: 2
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xeaeeb0)
D:/GoSDK/go1.17.3/src/runtime/sema.go:56 +0x25
sync.(*WaitGroup).Wait(0x60)
D:/GoSDK/go1.17.3/src/sync/waitgroup.go:130 +0x71 func main(){
wg := sync.WaitGroup{}
wg.Add(3)
const Count = 3
ch1, ch2, ch3 := make(chan bool), make(chan bool), make(chan bool)
go func() {
defer wg.Done()
for i := 0; i < Count; i++ {
<-ch1
fmt.Println("dog:", i)
//notice 2
ch2 <- true
}
}()
go func() {
defer wg.Done()
for i := 0; i < Count; i++ {
//wait 1
<-ch2
fmt.Println("cat:", i)
//notice 3
ch3 <- true
}
}()
go func() {
defer wg.Done()
for i := 0; i < Count; i++ {
//wait 2
<-ch3
fmt.Println("fish:", i)
//notice 1
ch1 <- true
}
}()
//notic 1
ch1 <- true
wg.Wait()
}发布于 2022-05-01 11:37:29
这里的问题是,没有go例程在等待ch1。因此,在第三个goroutine锁(ch1 <- true)的最后一次迭代中。所以你需要的是一种方法来认识到这条链停止了。我简短而谦逊的建议:
func main() {
wg := sync.WaitGroup{}
wg.Add(3)
const Count = 3
ch1, ch2, ch3 := make(chan bool), make(chan bool), make(chan bool)
chainEnded := make(chan struct{})
go func() {
defer wg.Done()
for i := 0; i < Count; i++ {
<-ch1
fmt.Println("dog:", i)
//notice 2
ch2 <- true
}
chainEnded <- struct{}{}
}()
go func() {
defer wg.Done()
for i := 0; i < Count; i++ {
//wait 1
<-ch2
fmt.Println("cat:", i)
//notice 3
ch3 <- true
}
}()
go func() {
defer wg.Done()
for i := 0; i < Count; i++ {
//wait 2
<-ch3
fmt.Println("fish:", i)
//notice 1
ch1 <- true
}
}()
//notic 1
ch1 <- true
<-chainEnded // wait for the loop to end and send to this chan
<-ch1 // unblock the attempt to chain of the last routine
wg.Wait()
}https://stackoverflow.com/questions/72076194
复制相似问题