dow46218 2017-07-28 07:05
浏览 45
已采纳

golang通道与make相关的死锁

I'm new to Golang and meet the strange behavior of Go's channel. The question is described as the following.

package main

import "fmt"

func main() {
    ch := make(chan int)

    fmt.Println("len:", len(ch))
    fmt.Println("cap:", cap(ch))
    fmt.Println("is nil:", ch == nil)

    go func(ch chan int){
        ch <- 233
    }(ch)

    fmt.Println(<- ch)

}

When I run the code above, I got result like this:

len: 0
cap: 0
is nil: false
233

The len and cap of the channel ch seem wierd but the code still works. But when I run this code:

package main

import "fmt"

func main() {
    ch := make(chan int)

    fmt.Println("len:", len(ch))
    fmt.Println("cap:", cap(ch))
    fmt.Println("is nil:", ch == nil)

    ch <- 233 // Here changes!

    fmt.Println(<- ch)

}

The result became: len: 0 cap: 0 is nil: false fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
    /tmp/sandbox640280398/main.go:12 +0x340

What's more, when I change the second code piece like the following: package main

import "fmt"

func main() {
    ch := make(chan int, 1) //Here changes!

    fmt.Println("len:", len(ch))
    fmt.Println("cap:", cap(ch))
    fmt.Println("is nil:", ch == nil)

    ch <- 233

    fmt.Println(<- ch)

}

Things worked again, I got:

len: 0
cap: 1
is nil: false
233

So, can anybody tell me the following questions:

  1. Why make(chan int) return a channel with zero len and zero cap but still can work well in first code piece?

  2. Why the second code use the channel in the main function instead of a new goroutine cause the deadlock?

  3. Why I add a cap parameter to make in third code can fix the problem?

  4. What's the difference between the channel(in 1st and 2nd code) with the nil channel?

Thanks!

  • 写回答

1条回答 默认 最新

  • dongxian8858 2017-07-28 07:48
    关注

    You can create two types of channels: buffered channels and unbuffered channels.
    Buffered channel are those that has capacity: make(chan int, 10)
    Buffered channels allow you to send into them same amount of messages as their capacity without being blocked.
    Unbuffered channels has no capacity and that is why your sending goroutine will be blocked until another goroutine receive from it.

    1. It is unbuffered channel. You main goroutine is blocked on receiving from channel until new goroutine send message to it.

    2. Because you are using unbuffered channel your sending goroutine is blocked until another receive from it, but you have no other goroutines except that main one, so the program is in deadlock.

    3. Because of buffered goroutine. It has capacity of 1, so it is won't be problem to send one message to it and then receive it in the same goroutine. But you will be blocked if you try to send more than 1 message to it. ch <- 233; ch <- 233 - this code will cause a deadlock.

    4. Did get what you mean..., but if you try to receive or send to a nil channel you will be blocked: var ch chan int; <-ch or var ch chan int; ch <- 1

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)
  • ¥15 Windows11, backspace, enter, space键失灵