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

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

报告相同问题?

悬赏问题

  • ¥66 定制开发肯德基自动化网站下单软件
  • ¥20 vscode虚拟环境依赖包未安装
  • ¥15 odoo17关于owl开发js代码问题
  • ¥15 光纤中多普勒频移公式的推导
  • ¥15 怎么制作一个人脸识别门禁系统
  • ¥20 大华dss监控平台网络关闭登不进去
  • ¥15 请使用蚁群算法解决下列问题,并给出我完整的代码
  • ¥20 关于php录入完成后,批量更新数据库
  • ¥15 请教往复密封润滑问题
  • ¥15 cocos creator发布ios包