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

Go使用sync.Cond时出现all goroutines are asleep死锁原因求解

死锁原因分析

首先明确sync.Cond的核心特性:Cond.Broadcast() 和 Cond.Signal() 发出的信号是一次性无缓冲的,只会唤醒调用信号发送动作时,已经处于Cond.Wait()阻塞状态的goroutine,信号不会被留存给后续才调用Wait()的goroutine。

你注释掉subscribe函数内的sync.WaitGroup相关代码后,死锁的触发时序如下:

  • 主goroutine先后调用3次subscribe函数,每次启动一个处理点击事件的子goroutine后就直接返回,不需要等待子goroutine执行到指定位置
  • 3个事件处理子goroutine还没来得及执行到c.Wait()语句,主goroutine已经先执行了button.Clicked.Broadcast()广播,此时没有处于等待状态的goroutine,这个广播信号直接作废,没有任何效果
  • 主goroutine接下来执行clickRegistered.Wait(),进入阻塞状态,等待3个事件回调执行完毕后调用Done()减计数
  • 后续3个事件处理子goroutine先后执行到c.Wait()语句,进入阻塞状态等待广播/信号,但此前的广播已经发送完成,不会再有新的信号触发它们唤醒,永远不会执行后续的fn()和clickRegistered.Done()
  • 最终所有goroutine都处于永久阻塞状态,Go运行时检测到没有活跃goroutine,抛出all go routines are asleep的死锁错误

原本被你注释掉的内部sync.WaitGroup的作用就是做同步保证:每次subscribe调用必须等到对应的子goroutine已经启动、即将进入Wait()阻塞状态时才会返回,这样三次subscribe全部执行完成时,3个事件处理goroutine都已经处于等待状态,后续主goroutine发送的Broadcast才能成功唤醒所有goroutine执行回调,不会出现信号丢失的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 17:24:03