ConcurrentProgrammingWithGo icon indicating copy to clipboard operation
ConcurrentProgrammingWithGo copied to clipboard

listing7.14 Receive early c.capacitySema.Release() call?

Open alsoLut opened this issue 4 months ago • 1 comments

I guess a more correct impl would be:

func (c *Channel[M]) Receive() M {
    c.sizeSema.Acquire()
    c.mutex.Lock()
    v := c.buffer.Remove(c.buffer.Front()).(M)
    c.mutex.Unlock()
    c.capacitySema.Release()
    return v
}

In the original implementation, if 100 goroutines call Receive() on an empty channel, all of them execute the first line capacitySema.Release() but then block at sizeSema.Acquire(). If then 100 Send() calls occur, they would all fill the buffer unchecked. Right?

alsoLut avatar Sep 13 '25 12:09 alsoLut

Hi there and thank you for your feedback.

In the original implementation we wanted to implement synchronous behaviour similar to the Go channels. In the implementation, when we want synchronous behaviour we create a Channel with capacity of 0. This will enable a producer to wait on the capacitySema until there is a consumer. Once a consumer calls Receive, the c.capacitySema.Release() will unblock producer's Acquire() and the message will be exchange via the buffer.

The problem with the above implementation is that it doesn't support synchronous behaviour similar to the Go channels. The above implementation will block indefinitely when you specify a capacity of 0.

cutajarj2 avatar Sep 26 '25 09:09 cutajarj2