一个基本的Golang流(通道)死锁

时间:2017-10-09 12:01:36

标签: go stream deadlock bytestream

我正在尝试使用go stream,我有一些“愚蠢”的问题。

我已经完成了一个带有字节限制范围的原始流示例,这里是工作代码,这是我的问题。

1 - 为什么此代码在新行显示1和2?为什么它不显示12?是否从字节限制流中删除了第一个字节数? (但是当我们已经推出1号码时,我们如何才能将2号码推入流中?)我无法理解它

package main

import "fmt"

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}
It shows:
1
2

2问题 - 我尝试使用此代码来了解它是如何工作的,我已经删除了字节范围,并且我遇到了死锁错误。为什么会这样?谢谢!

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
    /tmp/sandbox557775903/main.go:7 +0x60

死锁错误代码:

package main

import "fmt"

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

感谢您的帮助!抱歉原始问题。

2 个答案:

答案 0 :(得分:1)

因为频道操作员<-只从频道中获取1个元素。如果您希望将它们打印在一起,请尝试:fmt.Println("%v%v", <-c, <-c)"

频道创建中的最后一个号码make(chan int, 2)表示频道缓冲区 - 其存储项目的容量。因此,您可以轻松地将2个项目推送到频道。但是,如果你试图再推一件物品,会发生什么?操作将被阻止,因为在另一个goroutine将从通道和可用空间读取之前没有空间。

这同样适用于所有频道 - 未受影响的频道在第一次元素写作时被阻止。直到一些goroutine从频道读取。

因为没有goroutine可读,所以永远写一个锁。您可以在开始阅读goroutine之前解决它。

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

这种方式不会被锁定但会开始传输项目。

答案 1 :(得分:0)

  

1 - 为什么此代码在新行显示1和2?

答案:因为你使用的是Println()方法。如果你想在一行上使用Print()

  

2我尝试使用此代码来了解它是如何工作的,我已经删除了字节rande并且我遇到了死锁错误。为什么会这样?

就代码所示,您永远不会为您创建的频道启动并发阅读器。因为它是无缓冲的,所以对它的任何写入都会阻塞,直到有人在某处从另一端读取。