gpt4 book ai didi

go - 使用简单的测试场景出现 fatal error : all goroutines are asleep - deadlock!

转载 作者:数据小太阳 更新时间:2023-10-29 03:16:14 25 4
gpt4 key购买 nike

我正在尝试重现问题并使用以下代码得出最小用例。如果我关闭所有 channel (绕过 i == 0 测试),一切都会按预期进行。 Wg 状态递减并触发完成,main 退出正常。当我(故意)跳过关闭其中一个 channel 时,我希望主例程等待 WaitGroup 信号量在这种情况下无限期阻塞。相反,我得到一个错误:“ fatal error :所有 goroutines 都睡着了 - 死锁!”。这是为什么?我一定是错过了一些基本的东西,或者这个运行时过于热心了?

package main

import (
"fmt"
"sync"
)

const N int = 4

func main() {

done := make(chan struct{})
defer close(done)

fmt.Println("Beginning...")

chans := make([]chan int, N)
var wg sync.WaitGroup

for i := 0; i < N; i++ {
wg.Add(1)
chans[i] = make(chan int)
go func(i int) { // p0
defer wg.Done()
for m := range chans[i] {
fmt.Println("Received ", m)
}
fmt.Println("Ending p", i)
}(i)
}

go func() {
wg.Wait()
done <- struct{}{} // signal main that we are done
}()

for i := 0; i < N; i++ {
fmt.Println("Closing c", i)
if i != 0 { // Skip #0 so wg doesn't reach '0'
close(chans[i])
}
}

<-done // wait to receive signal from anonymous join function
fmt.Println("Ending.")
}

更新:我编辑了代码以避免竞争条件。仍然收到此错误。

if i != 0是因为它是故意的。我希望 wg.Wait 永远阻塞(其信号量永远不会达到 0。)为什么我不能那样做?好像我用的一样<-done没有匹配 done <- struct{}{}别的地方。在那种情况下,编译器也会提示吗?

最佳答案

这是发生了什么:

  • 第一个 go func(i int) { goroutine 没有退出,因为 chans[0] 没有关闭。
  • 因为 goroutine 没有退出,所以 wg.Done 没有被调用。
  • 由于前一点,对 wg.Wait() 的调用将永远阻塞。
  • Main 永远阻塞,因为信号没有发送到done

您可以通过删除 if i != 0 { 来修复死锁,但还有另一个问题。 WaitGroup 有一场比赛。在调用 wg.Add(1) 之前调用 wg.Done() 是可能的。在启动 goroutine 之前调用 wg.Add() 以避免竞争。

关于go - 使用简单的测试场景出现 fatal error : all goroutines are asleep - deadlock!,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34583936/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com