On Saturday, April 7, 2018 at 9:04:38 AM UTC-4, T L wrote: > > > > 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 { > raceacquire(qp) > racerelease(qp) > 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) > c.recvx++ > 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 > unlockf() > 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 code. >
The only reason would be, if no bugs in code, in a very low possibility, the 99 send goroutines haven't been ready to send yet when a receive is finished. > > >> >> On Sat, 7 Apr 2018 at 12:54, T L <tapi...@gmail.com> 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. >>> 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.