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

Golang使用WaitGroups实现worker时触发all goroutines are asleep死锁问题

死锁触发原因
  • 核心是执行顺序逻辑闭环:你的代码中close(messageChannel)的位置放在了wg.Wait()之后,形成了双向等待的死锁:
    1. worker的退出逻辑依赖for range messageChannel终止:Go语言中for range遍历无缓冲/有缓冲channel时,只有channel被显式关闭且所有缓冲数据都被读取完毕,循环才会退出;如果channel未关闭且为空,worker会永久阻塞在遍历步骤,永远不会执行defer wg.Done()
    2. main goroutine 执行到stop(wg)时会卡在wg.Wait(),必须等所有worker的wg.Done()都执行完成,才会继续执行后续的close(messageChannel)逻辑
  • 两边互相等待对方先执行操作,没有任何goroutine能继续推进逻辑,就触发了Go运行时的死锁检测,抛出对应的fatal error。
修复方案

将关闭channel的操作提前到wg.Wait()之前,发完全部任务后立刻关闭channel,通知worker没有更多任务需要处理:

func main() {
    wg := new(sync.WaitGroup)
    messageChannel := make(chan string, 50)

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go worker(wg, messageChannel)
    }

    for i := 0; i < 10; i++ {
        messageChannel <- fmt.Sprint(i)
    }
    // 发完所有任务立刻关闭channel,通知worker退出
    close(messageChannel)
    stop(wg)
}

修复后执行逻辑:所有worker读完channel中缓存的10条任务后,检测到channel已关闭,自动退出for循环,执行defer wg.Done(),5个worker全部退出后wg.Wait()返回,程序正常退出。

内容的提问来源于stack exchange,提问作者shyam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 23:45:02