当从下面的 goroutine 在 channel 上发送时,我有以下代码进入死锁:
package main
import (
"fmt"
"sync"
)
func main() {
for a := range getCh(10) {
fmt.Println("Got:", a)
}
}
func getCh(n int) <-chan int {
var wg sync.WaitGroup
ch := make(chan int)
defer func() {
fmt.Println("closing")
wg.Wait()
close(ch)
}()
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < n; i++ {
ch <- i
}
}()
wg.Add(1)
go func() {
defer wg.Done()
for i := n; i < 0; i-- {
ch <- i
}
}()
return ch
}
我知道在defer
中使用wg.Wait()
是合法的。但是我一直没能在以 channel 作为返回值的函数中找到用途。
最佳答案
我认为您犯的错误是您认为 deferred
函数也将异步运行。但事实并非如此,因此 getCh()
将阻塞在其延迟部分,等待 WaitGroup。但是由于没有人从 channel 中读取,写入 channel 的 goroutines 无法返回,因此 WaitGroup 导致死锁。尝试这样的事情:
func getCh(n int) <-chan int {
ch := make(chan int)
go func() {
var wg sync.WaitGroup
wg.Add(1)
go func(n int) {
defer wg.Done()
for i := 0; i < n; i++ {
ch <- i
}
}(n)
wg.Add(1)
go func(n int) {
defer wg.Done()
for i := n; i > 0; i-- {
ch <- i
}
}(n)
wg.Wait()
fmt.Println("closing")
close(ch)
}()
return ch
}
关于go - 等待 sync.Waitgroup 延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37943036/