如何正确关闭Channel以解决Go程序死锁问题?
解决goccm限制goroutine时的通道死锁问题
你的代码死锁确实是因为chanStr没关闭,而且c.WaitAllDone()的位置错了——for range chanStr会一直阻塞等待通道关闭,后面的c.WaitAllDone()根本跑不到,导致程序卡死。
利用goccm自带的等待机制,我们可以把关闭通道的逻辑放到一个单独的goroutine里,避免阻塞主goroutine的接收循环。修改后的代码如下:
func main() { c := goccm.New(5) chanStr := make(chan string) lines := []string{"aaaaaa", "fffff", "ddddd", "eeeee"} for _, value := range lines { value := value c.Wait() go func() { chanStr <- value c.Done() }() } // 单独起goroutine等待所有任务完成后关闭通道 go func() { c.WaitAllDone() close(chanStr) }() // 遍历接收数据,通道关闭后自动退出循环 for value := range chanStr { fmt.Println(value) } }
关键改动说明:
- 新增的goroutine专门负责等待所有并发任务执行完毕,随后关闭
chanStr,这样主goroutine的for range循环在接收完所有数据后,会因为通道关闭而正常退出。 - 不需要额外维护done通道,goccm的
WaitAllDone()已经帮你处理了等待所有goroutine完成的逻辑。
内容的提问来源于stack exchange,提问作者sheki meki
相关产品推荐
相关产品推荐

