On Saturday, April 7, 2018 at 8:39:22 AM UTC-4, Steven Hartland wrote:
> You should use a wait group to guarantee the behaviour of this.

I know there are other ways to do the task.
I just feel the runtime behavior is some strange.

The following is the code to receive a value if there are some goroutines 
are wariting in sending.

func recv(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func()) {
       if c.dataqsiz == 0 {
              if raceenabled {
                     racesync(c, sg)
              if ep != nil {
                     // copy data from sender
                     recvDirect(c.elemtype, sg, ep)
       } else {
              // Queue is full. Take the item at the
              // head of the queue. Make the sender enqueue
              // its item at the tail of the queue. Since the
              // queue is full, those are both the same slot.
              qp := chanbuf(c, c.recvx)
              if raceenabled {
                     raceacquireg(sg.g, qp)
                     racereleaseg(sg.g, qp)
              // copy data from queue to receiver
              if ep != nil {
                     typedmemmove(c.elemtype, ep, qp)
              // copy data from sender to queue
              typedmemmove(c.elemtype, qp, sg.elem)
              if c.recvx == c.dataqsiz {
                     c.recvx = 0
              c.sendx = c.recvx // c.sendx = (c.sendx+1) % c.dataqsiz
       sg.elem = nil
       gp := sg.g
       gp.param = unsafe.Pointer(sg)
       if sg.releasetime != 0 {
              sg.releasetime = cputicks()
       goready(gp, 4)

>From the code, we can find that the receive from the only buffer
and the fill to the only buffer with the next queuing value
are really in one atomic operation.

But I don't know why two weeks ago, the behavior is not consistent with the 

> On Sat, 7 Apr 2018 at 12:54, T L <tapi...@gmail.com <javascript:>> wrote:
>> On Monday, March 26, 2018 at 4:09:24 PM UTC-4, Marvin Renich wrote:
>>> It seems that you understand why you are seeing the behavior you 
>>> reported, but you are questioning whether the spec either does or should 
>>> guarantee that reading from a channel with a goroutine waiting to send 
>>> on that channel will fill the buffer as an atomic part of the read. 
>>> As others have said, the spec does not guarantee this.  I would like to 
>>> add that I believe it shouldn't.  Suppose goroutine A is currently 
>>> blocked waiting to send on a channel.  Now goroutine B reads from that 
>>> channel.  If the refill of the channel must happen atomically with the 
>>> read from that channel, now goroutine B must be put in a blocked state 
>>> waiting for goroutine A to finish its send.  This contradicts the spec 
>>> at [1] which states 
>>>   ...communication succeeds without blocking if the buffer is not full 
>>>   (sends) or not empty (receives). 
>>> If you think about how this is likely to be implemented (including 
>>> considerations for GOMAXPROC and multicore vs single core systems), you 
>>> should realize that, while it would be possible to implement 
>>> atomic-refill, it would give no (or very little) benefit and might have 
>>> undesirable performance effects. 
>>> As an aside, I think the reason Jake is seeing 100 lines of output and 
>>> you only see 1 is likely to be the difference between GOMAXPROC=1 and 
>>> greater than 1.  If GOMAXPROC=1, the scheduler may force a running 
>>> goroutine to yield after receiving, but before returning from the 
>>> receive operation.  In other words, the receive happens without 
>>> blocking, but the scheduler thinks that is a convenient point for giving 
>>> another goroutine an opportunity to run. 
>> No, I tried both GOMAXPROC=1 and GOMAXPROC=4. Same results.
>> It is strange that I just tried it again, now there will be always 100 
>> lines outputted,
>> for both GOMAXPROC=1 and GOMAXPROC=4, for both v1.10 and v1.10.1.
>> Quite strange.
>>> ...Marvin 
>>> [1] https://golang.org/ref/spec#Channel_types
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golang-nuts...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.

You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to