具有无缓冲通道的Golang例程

时间:2018-01-24 07:16:26

标签: go

我正在阅读这本书Go in action

这就是unbuffered channel的描述方式:

  

无缓冲通道是无法容纳任何值的通道   在它收到之前。这些类型的频道都需要发送   接收goroutine在任何之前的同一时刻准备好   发送或接收操作可以完成。如果两个goroutines不是   在同一时刻准备好,通道使goroutine   执行其各自的发送或接收操作首先等待。   同步是发送和发送之间的交互所固有的   在频道收到。一个人不可能一个接一个地发生。

本书使用下图来说明unbuffered channel

enter image description here

所以我想知道如果有三个或更多goroutine共享同一个channel怎么样?

例如,三个goroutine GA GB GC共享相同的频道c

现在GA通过c发送消息后,我们如何确保GBGC都会收到消息?因为正如书中所说:

  

这些类型的频道需要发送和接收goroutine   在同一时刻做好准备

这意味着当两个goroutine正在交换消息时,第三个必须丢失消息。

这是goroutine运行的正确方法吗?

4 个答案:

答案 0 :(得分:3)

通过频道发送的消息将传递给接收goroutine的一个

假设您有三个goroutine,一个发送和两个接收,发送goroutine需要发送两个消息,以便接收goroutine取消阻止,例如this

var c = make(chan int)

go func() { fmt.Printf("got %d\n", <-c) }()
go func() { fmt.Printf("got %d\n", <-c) }()

c <- 1
c <- 2

另请注意,这也需要接收goroutines分别读取一个消息。如果他们要在循环中执行它,其中一个可能会收到两个消息而另一个都没有。

答案 1 :(得分:0)

如果一个频道上有两个或多个接收者和一个发送者(缓冲/未缓冲)并且发送者通过该频道发送消息,则所有接收者中只有一个会收到消息。

答案 2 :(得分:0)

你是对的,只有一个接收者可以从一个频道(缓冲或非缓冲)获得一个特定的消息。如果您希望多个接收器读取来自通道的所有消息,则必须在原始通道和接收器之间放置一个多路复用器,它将读取消息并将它们转发到N个通道,每个接收器一个。 / p>

如果我们将它绘制出来,它会看起来像这样(GA是发件人,GBGCGZ是接收者,ccBcCcZ是渠道,multiplexer是自解释的。)

                         +-> [cB] -> GB
                         |
GA -> [c] -> multiplexer +-> [cC] -> GC
                         |
                         ...
                         |
                         +-> [cZ] -> GZ

您还可以查看this answer代码示例。

答案 3 :(得分:0)

假设goroutine A和B正从无缓冲通道c读取。它们都被阻止,因为通道是无缓冲的。

Goroutine D在频道中写点东西。 A或B中的一个将接收数据并将被解锁,另一个将被阻止,直到D或其他goroutine将另一个东西写入频道。