了解Go中的通道执行顺序

时间:2013-06-02 18:42:13

标签: go channel

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


我正在处理Rob Pike在Google I / O 2012上提供的Go Concurrency Patterns幻灯片,有关排序的示例有点令人困惑。在Slide 29上有一个示例,说明如何在多路复用之后恢复排序。简而言之,来自多个通道的消息被多路复用到单个通道中,并且每个消息结构共享一个名为“waitForIt”的通道。此通道旨在确保提供消息的服务(在引用的示例中为无聊的服务)和服务的客户端按顺序进行。我不明白为什么,为了对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结构共享同一个通道,为什么需要两次等待?不应该只有一个&lt; -wait 就足够了,即

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

如果等待变量中有两个发送,如 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

为什么第二个发送到等待在正确序列所需的同一个通道上?

2 个答案:

答案 0 :(得分:2)

阅读正确的例子[1]我猜你已经知道为什么你需要两个“等待它”。

以防万一:

您从频道中读取了两条消息。 每个消息生成器(无聊的goroutine)都在等待“等待它”。 所以你需要发送两个“等待它”,否则其中一个将继续等待。

如果您只通过频道发送一个“真实”,那么Joe会收到“等待它”,并且可以发送新消息,但Ann会一直等待(或反转)。

我想在这一点上你的程序将陷入僵局。您想要阅读两条消息,但只能接收一条消息(来自Joe)。

我没有测试过,但我想是的。如果我错了,请告诉我。

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

答案 1 :(得分:0)

上面的测序示例不正确。可以找到正确的示例here