为了账号安全,请及时绑定邮箱和手机立即绑定

将两个 fmt.printlns 与 go 例程一起使用时出现死锁?

将两个 fmt.printlns 与 go 例程一起使用时出现死锁?

Go
PIPIONE 2023-03-21 10:23:21
我正在尝试学习围棋,并且正在操场上进行试验。我有一个非常简单的代码。我试图在 go 例程中同时使用 Structs 和 Slices。我不确定这是否是我会在生产中使用的东西,但它似乎有点不对劲,所以在这里:func main() {    routinemsg := make(chan []Person)    routinemsg2 := make(chan []Person)    // create the person records    p1 := newPerson("john doe", 25)    p2 := newPerson("dohn joe", 52)    p3 := newPerson("bohn joo", 30)    // send a slice of Person to the first routine    go func() { routinemsg <- []Person{p1, p2} }()    // retrieve the slice from the first routine[in the append]    // append p3 to the slice retrieved from the first routine    // send the new slice to the second routine    go func() { routinemsg2 <- append(<-routinemsg, p3) }()        // I am able to see the first Println but when I insert the second one I get a deadlock error    // also, same error if I use one Println with 2 arguments.    fmt.Println(<-routinemsg)    fmt.Println(<-routinemsg2)}我听说过等待小组,但还不了解他们!所以,对我好点:D,谢谢你抽出时间
查看完整描述

2 回答

?
LEATH

TA贡献1936条经验 获得超6个赞

上只有一个发送操作routinemsg,但您有 2 个接收操作:一个在已启动的 goroutine 中,另一个在 goroutine 中main。一个发送的值只能被一个接收者接收一次。

如果启动的 goroutine 从routinemsgfirst 接收,那么这将是一个死锁:接收将main永远阻塞。

如果maingoroutine 将首先接收,那么启动的 goroutine 将永远阻塞(试图从它接收),因此它永远不会发送任何东西 on ,因此来自inroutinemsg2的接收也将永远阻塞:再次死锁。routinemsg2main

删除fmt.Println(<-routinemsg)中的行main(),然后最终接收 fromroutinemsg2可以(最终)继续并打印包含p1,p2和 的切片p3

[{john doe 25} {dohn joe 52} {bohn joo 30}]

在Go Playground上尝试一下。


查看完整回答
反对 回复 2023-03-21
?
慕斯王

TA贡献1864条经验 获得超2个赞

如果您使用如下所示的缓冲通道,

    buffered := make(chan string, 2)
    buffered <- "1"
    buffered <- "2"

    fmt.Println(<-buffered)
    fmt.Println(<-buffered)

您可以从同一通道多次发送和接收值。

但是,您仍然可以通过传递给make 的参数来限制发送和接收的次数!此外,对于缓冲通道,您将始终按照发送到通道的顺序接收值。

因此,您从第二个接收器收到的第二个值将始终是发送到通道的第二个值。


查看完整回答
反对 回复 2023-03-21
  • 2 回答
  • 0 关注
  • 61 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信