【问题标题】:Deadlock when using two fmt.printlns with a go routine?将两个 fmt.println 与 goroutine 一起使用时出现死锁?
【发布时间】:2022-11-26 21:09:27
【问题描述】:

我正在尝试学习围棋,并且正在操场上进行试验。我有一个非常简单的代码。我试图在 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,谢谢你抽出时间

【问题讨论】:

    标签: go goroutine


    【解决方案1】:

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

    如果启动的 goroutine 首先从 routinemsg 接收,那么它将是一个死锁:main 中的接收将永远阻塞。

    如果 main goroutine 首先接收,那么启动的 goroutine 将永远阻塞(试图从它那里接收),因此它永远不能在 routinemsg2 上发送任何东西,因此在 main 中从 routinemsg2 接收也会阻塞永远:再次陷入僵局。

    删除main()中的fmt.Println(&lt;-routinemsg)行,然后来自routinemsg2的最终接收可以(最终)继续并打印包含p1p2p3的切片:

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

    Go Playground 上试试。

    【讨论】:

    • 嘿,谢谢你的时间!因此,与其在两个不同的地方接收 routinemsg2,我应该在一个地方接收并将其存储在一个变量中,然后再使用该变量。凉爽的!如果有的话,你能分享一篇文章或任何类型的资源吗?
    • 通道不复制数据。如果你在上面发送一个值,它只能被接收一次,而不是在多个地方多次接收。请注意,如果将接收到的值存储在变量中,则必须同步从多个 goroutine 访问该变量。您也可以选择两次发送一个值,或者一次收到就重新发送,但每个发送的值只能收到一次。
    【解决方案2】:

    作为@icza 回答的补充:如果你使用缓冲通道像下面,

    buffered := make(chan string, 1)
    

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

    然而,您仍然可以通过传入的参数限制发送和接收的次数制作!此外,使用缓冲通道,您将总是按照发送到通道的顺序接收值。

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

    【讨论】:

      猜你喜欢
      • 2016-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-14
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多