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

为何这两个Goroutine未发生永久阻塞?

为什么你的Goroutines没有永久阻塞?

嘿,我来帮你搞清楚这个问题的关键!你觉得这两个goroutine应该永久阻塞,但实际能正常运行,核心原因是你误解了锁和通道操作的关系——你的receive()函数根本没碰那把互斥锁,所以send()持有锁完全不会阻止receive()接收通道数据!

让我们一步步拆解代码的实际执行流程:

  • 首先,main函数初始化了无缓冲通道s.ch,给WaitGroup加了2个计数,接着启动send()和receive()两个goroutine。
  • 假设send()先被调度:
    1. 它先拿到s.mu锁,然后尝试往无缓冲通道s.ch发数据5。无缓冲通道的发送会阻塞,必须等有goroutine来接收数据才能继续。
    2. 这时候receive()被调度执行,它直接执行num := <-s.ch(完全不需要获取锁),顺利接收到5并打印。
    3. receive()调用s.wg.Done(),把WaitGroup计数减1。
  • 一旦receive()完成了通道接收,send()里的阻塞就解除了:
    1. send()继续执行s.mu.Unlock()释放锁,接着调用s.wg.Done()。
  • 最后main函数里的s.wg.Wait()发现计数归零,程序正常退出。

哪怕是receive()先被调度,它也只会在num := <-s.ch处阻塞,等send()拿到锁并完成通道发送后,同样能顺利走完流程,根本不会出现永久阻塞的情况。

你的分析误区在于误以为receive()的通道接收需要等待锁,但实际上receive()里完全没有加锁逻辑,那把互斥锁只在send()里被使用,和receive()的通道操作毫无关系。无缓冲通道的发送/接收是独立的同步操作,只要有对应的接收/发送方,就能完成数据传递、解除阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:58:09