Go语言发送完channel所有值后仍出现死锁问题求助
Go并发channel死锁问题修复
死锁产生原因
- 代码中使用的无缓冲channel
done从未执行关闭操作,当10个发送数据的子goroutine全部执行完毕退出后,主goroutine的无限循环仍在阻塞等待done返回新值,此时程序仅剩余主goroutine处于阻塞状态,触发运行时死锁。 - 注释中预留的
sync.WaitGroup逻辑使用逻辑错误:若直接在主goroutine中执行wg.Wait()后关闭channel,会导致主goroutine先阻塞在等待逻辑,且未单独开goroutine处理等待+关闭的逻辑,无法同时兼顾发送完成检测和接收端的正常运行。
修复后完整代码
package main import ( "fmt" "sync" ) // 输出 10 20 30 ... 100 func main() { wg := sync.WaitGroup{} done := make(chan int) for i := 1; i <= 10; i++ { wg.Add(1) go func(i int) { defer wg.Done() done <- i * 10 }(i) } // 异步等待所有发送端完成后关闭channel,避免阻塞主goroutine的接收逻辑 go func() { wg.Wait() close(done) }() // channel关闭且所有数据读取完成后自动退出循环 for value := range done { fmt.Println("received is ", value) } }
核心改动说明
- 启用
sync.WaitGroup跟踪所有子goroutine的生命周期,每个子goroutine启动前计数+1,执行完成后通过defer触发计数-1。 - 单独启动一个异步goroutine执行等待逻辑,所有子goroutine执行完成(即所有数据都已发送到channel)后,再关闭
donechannel,不会出现提前关闭导致的发送panic问题,也解决了channel不关闭导致的接收端死锁问题。 - 主goroutine改用
for range遍历channel,当channel关闭且所有已发送数据都被读取完成后,遍历会自动终止,无需手动判断接收状态位。
内容的提问来源于stack exchange,提问作者mohammed yaqub
相关产品推荐
相关产品推荐

