为何这两个Goroutine未发生永久阻塞?
为什么你的Goroutines没有永久阻塞?
嘿,我来帮你搞清楚这个问题的关键!你觉得这两个goroutine应该永久阻塞,但实际能正常运行,核心原因是你误解了锁和通道操作的关系——你的receive()函数根本没碰那把互斥锁,所以send()持有锁完全不会阻止receive()接收通道数据!
让我们一步步拆解代码的实际执行流程:
- 首先,main函数初始化了无缓冲通道
s.ch,给WaitGroup加了2个计数,接着启动send()和receive()两个goroutine。 - 假设
send()先被调度:- 它先拿到
s.mu锁,然后尝试往无缓冲通道s.ch发数据5。无缓冲通道的发送会阻塞,必须等有goroutine来接收数据才能继续。 - 这时候
receive()被调度执行,它直接执行num := <-s.ch(完全不需要获取锁),顺利接收到5并打印。 receive()调用s.wg.Done(),把WaitGroup计数减1。
- 它先拿到
- 一旦
receive()完成了通道接收,send()里的阻塞就解除了:send()继续执行s.mu.Unlock()释放锁,接着调用s.wg.Done()。
- 最后main函数里的
s.wg.Wait()发现计数归零,程序正常退出。
哪怕是receive()先被调度,它也只会在num := <-s.ch处阻塞,等send()拿到锁并完成通道发送后,同样能顺利走完流程,根本不会出现永久阻塞的情况。
你的分析误区在于误以为receive()的通道接收需要等待锁,但实际上receive()里完全没有加锁逻辑,那把互斥锁只在send()里被使用,和receive()的通道操作毫无关系。无缓冲通道的发送/接收是独立的同步操作,只要有对应的接收/发送方,就能完成数据传递、解除阻塞。
内容的提问来源于stack exchange,提问作者Yriuns
相关产品推荐
相关产品推荐

