【问题标题】:Understanding order of channel execution in Go了解 Go 中的通道执行顺序
【发布时间】:2013-05-28 23:20:53
【问题描述】:

注意:在这个问题中,我比较了两个版本的代码,并试图了解它们产生不同输出的原因。 play.golang.org 上两个版本的运行示例的链接是 FIG1FIG2


我正在研究 Rob Pike 在 2012 年 Google I/O 上展示的 Go Concurrency Patterns 幻灯片,而关于 Sequencing 的示例有点令人困惑。在Slide 29 上有一个示例,说明如何在多路复用 之后恢复排序。简而言之,来自多个通道的消息被多路复用到一个通道中,并且每个消息结构共享一个称为“waitForIt”的通道。此通道旨在确保提供消息的服务(在引用的示例中为 boring 服务)和服务的客户端是按顺序排列的。我不明白为什么,为了获得 A-B-A-B-A-B 的序列,客户端必须通过 waitForIt 通道发送 2 等待:

FIG1

for i := 0; i < 10; i++ {
    msg1 := <-c
    fmt.Printf("%s\n", msg1.str)
    msg2 := <-c
    fmt.Printf("%s\n", msg2.str)
    msg1.wait <- true
    msg2.wait <- true  /* why is this second wait necessary? */
}

如果 Message 结构共享同一个通道,为什么需要两次等待?一个 是否就足够了,即

FIG2

for i := 0; i < 10; i++ {
    msg1 := <-c
    fmt.Printf("%s\n", msg1.str)
    msg2 := <-c
    fmt.Printf("%s\n", msg2.str)
    msg1.wait <- true
}

然而,当使用单个等待时,消息 1 在输出开始时重复两次,然后顺序 A-B-A-B... 随之而来,因此输出是:

Message 1: Iteration 0
Message 2: Iteration 0
Message 1: Iteration 1 // Message 1 is repeated twice
Message 1: Iteration 2 // Here's the repetition
Message 2: Iteration 1
Message 1: Iteration 3
Message 2: Iteration 2
Message 1: Iteration 4
Message 2: Iteration 3
Message 1: Iteration 5

当有两次发送到wait变量时,如FIG1,顺序是A-B-A-B...从头开始:

Message 1: Iteration 0
Message 2: Iteration 0
Message 1: Iteration 1
Message 2: Iteration 1
Message 1: Iteration 2
Message 2: Iteration 2
Message 1: Iteration 3
Message 2: Iteration 3
Message 1: Iteration 4
Message 2: Iteration 4

为什么第二次发送到 wait 需要一个正确的序列?

【问题讨论】:

    标签: go channel


    【解决方案1】:

    上面的排序示例不正确。正确的例子可以在here找到。

    【讨论】:

      【解决方案2】:

      阅读正确的示例 [1] 我想您可能已经知道为什么您需要两者“等待它”。

      以防万一:

      您从频道中阅读了两条消息。 每个消息生成器(goroutine 里面很无聊)都在等待一个“等待它”。 所以你需要发送两个“等待它”,否则其中一个会一直等待。

      如果您通过通道只发送一个“真”,那么乔会收到它的“等待它”并可以发送一条新消息,但安一直在等待(或反转)。

      我猜此时你的程序会陷入僵局。您想阅读两条消息,但您只能收到一条(来自 Joe)。

      我没有测试过,但我认为是这样。让我知道我是否错了。

      [1]http://talks.golang.org/2012/concurrency/support/sequenceboring.go

      【讨论】:

      • 是的,这也是我的结论。这样做的好处是它允许通过多路复用通道从任意数量的 Messenger 接收消息的客户端保证在第一次迭代中接收消息的顺序将在所有后续迭代中保留。这就是为什么它被称为排序。
      猜你喜欢
      • 2019-01-30
      • 2018-02-02
      • 2021-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-31
      • 1970-01-01
      相关资源
      最近更新 更多