dongzhi9906 2013-09-06 14:47
浏览 64
已采纳

为什么在同一个goroutine中使用未缓冲的通道会导致死锁

I'm sure that there is a simple explanation to this trivial situation, but I'm new to the go concurrency model.

when I run this example

package main

import "fmt"

func main() {
    c := make(chan int)    
    c <- 1   
    fmt.Println(<-c)
}

I get this error :

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
    /home/tarrsalah/src/go/src/github.com/tarrsalah/tour.golang.org/65.go:8 +0x52
exit status 2

Why ?


Wrapping c <- in a goroutine makes the example run as we expected

package main

import "fmt"

func main() {
    c := make(chan int)        
    go func(){
       c <- 1
    }()
    fmt.Println(<-c)
}

Again, why ?

Please, I need deep explanation , not just how to eliminate the deadlock and fix the code.

  • 写回答

4条回答 默认 最新

  • dongxietao0263 2013-09-06 14:55
    关注

    From the documentation :

    If the channel is unbuffered, the sender blocks until the receiver has received the value. If the channel has a buffer, the sender blocks only until the value has been copied to the buffer; if the buffer is full, this means waiting until some receiver has retrieved a value.

    Said otherwise :

    • when a channel is full, the sender waits for another goroutine to make some room by receiving
    • you can see an unbuffered channel as an always full one : there must be another goroutine to take what the sender sends.

    This line

    c <- 1
    

    blocks because the channel is unbuffered. As there's no other goroutine to receive the value, the situation can't resolve, this is a deadlock.

    You can make it not blocking by changing the channel creation to

    c := make(chan int, 1) 
    

    so that there's room for one item in the channel before it blocks.

    But that's not what concurrency is about. Normally, you wouldn't use a channel without other goroutines to handle what you put inside. You could define a receiving goroutine like this :

    func main() {
        c := make(chan int)    
        go func() {
            fmt.Println("received:", <-c)
        }()
        c <- 1   
    }
    

    Demonstration

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥200 uniapp长期运行卡死问题解决
  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?
  • ¥15 乘性高斯噪声在深度学习网络中的应用
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败