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

Go语言无缓冲通道发送操作引发死锁问题咨询

Go语言channel死锁问题解答

你遇到的现象完全合理,是无缓冲channel使用的典型错误场景,属于Go并发编程的常见难点之一。

死锁原因说明

Go中未指定缓冲区大小的无缓冲channel,发送操作会永久阻塞直到有其他goroutine执行对应接收操作,同理接收操作也会阻塞直到有其他goroutine发送数据。

你贴出的错误代码执行流程如下:

func main() {
    c := make(chan int)
    q := make(chan int)
    w := make(chan int)
    c <- 1 // 死锁触发点
    go func() { q <- <-c}() // 上面代码阻塞时,这两个goroutine根本没有机会启动
    go func() { w <- <-q}()
    // go func() {c <- 1}()
    //c <- 1
    fmt.Println(<-w)
}
  • 代码运行到c <- 1时,还没有启动任何其他goroutine,不存在任何逻辑会接收channel c中的数据,main goroutine直接在这里永久阻塞
  • 整个程序此时只有main goroutine处于活跃阻塞状态,没有其他可运行的goroutine,触发Go runtime的死锁检测,抛出对应报错。

修改后可正常运行的逻辑

当你注释掉第5行的c <- 1,改成在启动两个goroutine之后再执行发送操作(或者把发送逻辑放到单独的goroutine中),执行流程变为:

  1. 先创建三个无缓冲channel
  2. 先启动两个后台goroutine,两个goroutine会分别进入阻塞状态,等待接收c、q的数据
  3. 此时执行c <- 1,已经有后台goroutine在等待接收c的数据,发送操作不会阻塞
  4. 数据顺次经过c→q→w传递,最后main goroutine从w接收到数据,程序正常退出。

这类问题是Go并发开发的高频易错点,核心注意规则:无缓冲channel的收发是同步操作,必须配对出现在不同的goroutine中,不要在main goroutine中先执行无缓冲channel发送、后启动接收goroutine。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 03:06:01