You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言发送完channel所有值后仍出现死锁问题求助

Go并发channel死锁问题修复

死锁产生原因

  • 代码中使用的无缓冲channeldone从未执行关闭操作,当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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 15:24:04