Go使用带缓冲通道出现all goroutines are asleep死锁问题求助
问题诊断
你对缓冲通道的基础使用没有问题,死锁的核心原因是通道关闭时机错误,触发了main goroutine的永久阻塞:
- 你把
close(valueChannel)放在了main函数的defer中,defer只会在main函数执行结束前才会触发 - main函数里的for循环会一直尝试从valueChannel读数据,只有通道被关闭时才会收到
ok=false的信号跳出循环 - 10个goroutine写完10条数据全部退出后,main goroutine读完10条数据后还会继续尝试读通道,此时通道没有被关闭也没有新数据写入,main goroutine永久阻塞,就触发了所有goroutine都休眠的死锁错误
修复方案
调整通道关闭逻辑即可:
- 移除main函数的
defer close(valueChannel) - 新增独立goroutine等待所有写goroutine结束后主动关闭通道
修复后的代码如下:
import ( "fmt" "math/rand" "sync" "time" ) func main() { valueChannel := make(chan int, 2) var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go doNothing(&wg, valueChannel) } // 所有写操作完成后关闭通道 go func() { wg.Wait() close(valueChannel) }() // 可以直接用for range遍历通道,通道关闭后自动退出循环 for v := range valueChannel { fmt.Println(v) } } func doNothing(wg *sync.WaitGroup, numChan chan int) { defer wg.Done() time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond) numChan <- 12 }
内容的提问来源于stack exchange,提问作者dhamechaSpeaks
相关产品推荐
相关产品推荐

