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 宇视监控服务器无法登录
  • ¥15 PADS Logic 原理图
  • ¥15 PADS Logic 图标
  • ¥15 电脑和power bi环境都是英文如何将日期层次结构转换成英文
  • ¥15 DruidDataSource一直closing
  • ¥20 气象站点数据求取中~
  • ¥15 如何获取APP内弹出的网址链接
  • ¥15 wifi 图标不见了 不知道怎么办 上不了网 变成小地球了
  • ¥50 STM32单片机传感器读取错误
  • ¥50 power BI 从Mysql服务器导入数据,但连接进去后显示表无数据