英文:
Understanding order of channel execution in Go
问题
我正在研究Rob Pike在2012年Google I/O上介绍的《Go并发模式》幻灯片,并且其中一个关于顺序的示例有点令人困惑。在第29张幻灯片上,有一个示例展示了如何在多路复用后恢复顺序。简而言之,来自多个通道的消息被多路复用到一个单一的通道中,每个Message结构共享一个名为"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 /* 为什么需要第二个等待信号? */
}
如果Message结构共享同一个通道,为什么需要两个等待信号?难道一个单独的_<-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
}
然而,当只使用一个等待信号时,输出的开头会重复两次Message 1,然后顺序A-B-A-B...开始,输出如下:
Message 1: Iteration 0
Message 2: Iteration 0
Message 1: Iteration 1 // Message 1重复两次
Message 1: Iteration 2 // 这里是重复的地方
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__中有两个对_wait_变量的发送时,从一开始就是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_的发送才能得到正确的顺序?
英文:
Note: In this question I compare two versions of code and try to understand why they produce different output. Links to running examples of the two versions on play.golang.org are FIG1 and FIG2.
I'm working through the Go Concurrency Patterns slides that Rob Pike presented at Google I/O 2012 and the example on Sequencing is a bit confusing. On Slide 29 there's an example of how to restore sequencing after multiplexing. In short, messages from multiple channels are multiplexed into a single channel and each Message structure shares a channel called "waitForIt". This channel is meant to ensure that the service that provides the messages (in the referenced example the boring service) and the client of the service are in sequence. I don't understand why, in order to have a sequencing of A-B-A-B-A-B, the client must send 2 waits over the waitForIt channel:
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? */
}
Why are two waits necessary if the Message struct is sharing the same channel? Shouldn't a single <-wait be sufficient, i.e.
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
}
Yet when a single wait is used, Message 1 is repeated twice at beginning of the output and then the sequencing A-B-A-B... ensues, so that what's output is:
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
When there's two sends into the wait variable, as in FIG1, the sequencing is A-B-A-B... from the beginning:
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
Why is the second send into wait on the same channel required for a correct sequence?
答案1
得分: 2
阅读正确的示例[1],我猜你可能已经知道为什么需要同时使用"wait for it"。
以防万一:
你从通道中读取了两条消息。
每个消息生成器(在boring内部的goroutine)都在等待"wait for it"。
所以你需要发送两个"wait for it",否则其中一个将会一直等待。
如果你只通过通道发送一个"true",那么Joe会收到它的"wait for it"并可以发送一条新消息,但是Ann会一直等待(或者反过来)。
我猜在这一点上你的程序将会发生死锁。你想要读取两条消息,但是你只能接收到一条(来自Joe)。
我没有测试过,但我认为是这样。如果我错了,请告诉我。
[1] http://talks.golang.org/2012/concurrency/support/sequenceboring.go
英文:
Reading the proper example [1] I guess that you already may know why you need both "wait for it".
Just in case:
You read two messages from the channel.
Each message generator (goroutine inside boring) is waiting for a "wait for it".
So you need to send two "wait for it", otherwise one of them will keep waiting.
If you send only one "true" through the channel then Joe receives its "wait for it" and can send a new message but Ann keeps waiting(or reversed).
I guess that at this point your program will be deadlocked. You want to read two messages, but you can receive only one (from Joe).
I have not tested it but I think so. Let me know if I'm wrong.
[1] http://talks.golang.org/2012/concurrency/support/sequenceboring.go
答案2
得分: 1
上面的排序示例是不正确的。正确的示例可以在这里找到。
英文:
The sequencing examples above are incorrect. The correct examples can be found here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论