0

I am reading the book Go in action.

This is how the unbuffered channel are described:

An unbuffered channel is a channel with no capacity to hold any value before it’s received. These types of channels require both a sending and receiving goroutine to be ready at the same instant before any send or receive operation can complete. If the two goroutines aren’t ready at the same instant, the channel makes the goroutine that performs its respective send or receive operation first wait. Synchronization is inherent in the interaction between the send and receive on the channel. One can’t happenwithout the other.

The book use the following figure to illustrate the unbuffered channel:

enter image description here

So I just wonder how about if there are three or more goroutine which share the same channel?

For example, three goroutine GA GB GC share the same channel c

Now once GA send message through c, how do we make sure that both GB and GC will receive the message? Since as the book said:

These types of channels require both a sending and receiving goroutine to be ready at the same instant

Which means when two goroutine are exchanging the message, the third must lost the message.

Is this the right way goroutine run?

hguser
  • 35,079
  • 54
  • 159
  • 293

4 Answers4

3

A message sent through a channel is delivered to exactly one receiving goroutine.

Assuming you have three goroutines, one sending and two receiving, the sending goroutine needs to send two messages for both the receiving goroutines to unblock, like 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

Also notice that this also requires the receiving goroutines to read exactly one message each. If they were to do it in a loop, one of them might receive both messages and the other none.

Josef Grahn
  • 1,585
  • 9
  • 12
  • How about the order ? Is it granted that the first goroutine will get 1 and the second get 2? – hguser Jan 24 '18 at 12:11
  • 1
    No, not generally. Even if the implementation uses a FIFO queue for waiting goroutines, there is a race between the two goroutines in the example I provided to be first to execute the receive operator (`<-`). You should generally avoid designs where you rely on concurrent things happening in a particular order. – Josef Grahn Jan 24 '18 at 13:49
  • So once you send `n` messages from somewhere, and there are `n` goroutines to receive the message, it is not granted that the receiver will receive the message by order as they are declared, however is it granted that all the `n` goroutines will get the message? For example, is it possible one of goroutine receive the message twice which make at least one goroutine get nothing? – hguser Jan 25 '18 at 00:21
  • If multiple receivers each execute the `<-` operator once, they will receive exactly one message each (assuming there are enough messages sent). These will be emitted from the channel in the same order as they were sent. However, unless you add additional logic to control in which order the receiving goroutines _execute_, you typically can't know which one will call `<-` first, nor in which order they will actually process the message after having received it. – Josef Grahn Jan 26 '18 at 13:07
1

You are right, only one receiver can get one specific message from a channel (buffered or unbuffered). If you want multiple receivers to read all messages from a channel, you will have to put a multiplexer between the original channel and the receivers, which would read the messages and forward them to N channels, one for each receiver.

If we would draw it out it would look something like this (GA is the sender, GB, GC, GZ are receivers, c, cB, cC, cZ are channels and multiplexer is self explanatory).

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

You can also look at this answer for a code example.

lmazgon
  • 1,215
  • 1
  • 21
  • 40
0

If there are 2 or many receivers and one sender on a channel(buffered/unbuffered) and sender sends a message through the channel, only one out of all the receivers will get the message.

vedhavyas
  • 1,101
  • 6
  • 12
0

Let say goroutine A and B are reading from unbuffered channel c. They are both blocked as the channel is unbuffered.

Goroutine D write something into channel. One of A or B will receive data and will be unblocked the other one stay blocked until D or other goroutine write another thing into channel.

Arman Ordookhani
  • 6,031
  • 28
  • 41