通道和等待组进入死锁



我很难处理go例程,也很难让它们在主go例程上与通道通信。为了简化,我的代码看起来像这样:


func main() {
channel := make(chan string)
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go performTest(channel, &wg, i)
}
wg.Wait()
close(channel)
for line := range channel {
fmt.Print(line)
}
}
func performTest(channel chan string, wg *sync.WaitGroup, i int) {
defer wg.Done()
// perform some work here
result := fmt.sprintf("Pretend result %d", i)
channel <- result
}

这似乎进入了某种僵局,但我不明白为什么。它在wg.Wait()上被卡住了,尽管我希望它在等待组上所有goroutine都调用了Done后继续。我在这里错过了什么?我想等待goroutines,然后迭代通道中的所有结果。

您可以在单独的go例程中等待组并关闭通道。如果通道关闭,您在通道上的范围将在收到最后一个发送的值后结束。

如果您只是等待,频道将不会收到任何内容。由于通道没有缓冲区,performTestgoroutines将无法发送。对于未缓冲的信道,发送操作将被阻止,直到收到为止。因此,延迟的wg.Done调用永远不会发生,并且您的程序处于死锁状态。由于CCD_ 5仅在执行了永久阻塞发送之后才被调用。

func main() {
channel := make(chan string)
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go performTest(channel, &wg, i)
}

// this is the trick
go func() {
wg.Wait()
close(channel)
}()
for line := range channel {
fmt.Print(line)
}
}
func performTest(channel chan string, wg *sync.WaitGroup, i int) {
defer wg.Done()
// perform some work here
result := fmt.Sprintf("Pretend result %dn", i)
channel <- result
}

https://play.golang.com/p/5pACJzwL4Hi

最新更新