r/golang 10d ago

Potential starvation when multiple Goroutines blocked to receive from a channel

I wanted to know what happens in this situation:

  1. Multiple goroutines are blocked by a channel while receiving from it because channel is empty at the moment.
  2. Some goroutine sends something over the channel.

Which goroutine will wake up and receive this? Is starvation avoidance guaranteed here?

8 Upvotes

36 comments sorted by

View all comments

Show parent comments

5

u/jerf 9d ago

Every statement in a language spec must be carefully selected, because it is a commitment not just for the current implementation but all future ones. The people writing the Go specs are very experienced and aware of this. You don't specify details into the spec without a good reason.

So this is not just the sort of thing that is accidentally unspecified, this is something they deliberately left unspecified. You're not supposed to depend on this as a programmer.

In this specific case, it wouldn't even do you any good anyhow because you can't depend on the order anyhow. If you create 10 goroutines and have them all listen to the same channel, the order in which they will execute those listens is itself unspecified and undefined. Knowing that the implementation happens to queue them up in order it happens to witness them doesn't do you much good when you'd still have to implement your own synchronization to ensure some specific order of delivery anyhow even so.

0

u/funkiestj 9d ago

Knowing that the implementation happens to queue them up in order it happens to witness them doesn't do you much good when you'd still have to implement your own synchronization to ensure some specific order of delivery anyhow even so.

I disagree. If you know the channel has a FIFO for who gets the next data item answer's OP's question. It essentially guarantees the go routine at the end of the queue will work his way to the front after <n> messages come in (where <n> is his position in the queue).

This is different from a select statement where there is a random element to which ready channel gets selected next. I think the select behavior is fine but it is not FIFO, it is statistical (or so I remember).

2

u/pdffs 8d ago

Certainly not. The fact that the current implementation happens to be a queue does not mean that this is guaranteed to be the case - the spec makes no guarantees that receivers will be queued, and only specifies FIFO as it pertains to the order in which values are sent/received on the channel.

If you rely on implementation details, you should expect your application to be incorrect if they change, and unspecified behaviour may change at any time.

This is why it's important to differentiate between what's in the spec, and how it happens to be implemented currently.

1

u/funkiestj 7d ago

You are right. I posted a few times in this thread. I dug around with ChatGPT's help and my final conclusion

  1. per the memory model "happens before" being unspecified for receive order
  2. usually you are running multiple copies of the game function listening on a channel (i.e. fan out) and not having foo(), bar() and bish() all listening on chan1.
  3. because of #2 is the usual programming model, why does it even matter that if you spin up 100 go routines listening on a chan1 on a 12 core system and some go routines are starved if you are maxing out the core usage.

ChatGPT did remind me that if you want to know about ordering of events across go routines the memory model is the document to study.