我正在阅读这本书Go in action
。
这就是unbuffered channel
的描述方式:
无缓冲通道是无法容纳任何值的通道 在它收到之前。这些类型的频道都需要发送 接收goroutine在任何之前的同一时刻准备好 发送或接收操作可以完成。如果两个goroutines不是 在同一时刻准备好,通道使goroutine 执行其各自的发送或接收操作首先等待。 同步是发送和发送之间的交互所固有的 在频道收到。一个人不可能一个接一个地发生。
本书使用下图来说明unbuffered channel
:
所以我想知道如果有三个或更多goroutine
共享同一个channel
怎么样?
例如,三个goroutine GA
GB
GC
共享相同的频道c
现在GA
通过c
发送消息后,我们如何确保GB
和GC
都会收到消息?因为正如书中所说:
这些类型的频道需要发送和接收goroutine 在同一时刻做好准备
这意味着当两个goroutine正在交换消息时,第三个必须丢失消息。
这是goroutine运行的正确方法吗?
答案 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
是发件人,GB
,GC
,GZ
是接收者,c
,cB
,cC
,cZ
是渠道,multiplexer
是自解释的。)
+-> [cB] -> GB
|
GA -> [c] -> multiplexer +-> [cC] -> GC
|
...
|
+-> [cZ] -> GZ
您还可以查看this answer代码示例。
答案 3 :(得分:0)
假设goroutine A和B正从无缓冲通道c
读取。它们都被阻止,因为通道是无缓冲的。
Goroutine D在频道中写点东西。 A或B中的一个将接收数据并将被解锁,另一个将被阻止,直到D或其他goroutine将另一个东西写入频道。