go's memory model for unbuffered channels

377 views
Skip to first unread message

liming

unread,
May 29, 2014, 4:32:40 AM5/29/14
to golan...@googlegroups.com
From go’s documentation

If the channel is unbuffered, the sender blocks until the receiver has received the value. If the channel has a buffer, the sender blocks only until the value has been copied to the buffer; if the buffer is full, this means waiting until some receiver has retrieved a value.

The following code is gaurantined to print “hello, world”

package main
var c = make(chan int, 10)
var a string

func f() {
     a = "hello, world"
     c <- 0
}

func main() {
     go f()
     <-c
     print(a)
}

if we change channel c to unbuffered channel:

package main
var c = make(chan int)
var a string

func f() {
     a = "hello, world"
     c <- 0
}

func main() {
     go f()
     <-c
     print(a)


Is it gaurantined to print “hello, world”

c<-0 will bock until <-c has received the value,
so c<-0 happens before <-c, as the assignment to a happens before c<-0,
so in the main function, it will print “hello, world” right?

But from go memory model, it says
A receive from an unbuffered channel happens before the send on that channel completes.

so print(a) in main function is not gaurantined to print “hello, world”


which analysis is right?




Matthew Kane

unread,
May 29, 2014, 9:59:01 AM5/29/14
to liming, golang-nuts
It is. The receive happens before the send completes. Earlier in the
memory model, we have:

Within a single goroutine, the happens-before order is the order
expressed by the program.

So, the assignment to a happens before the send, and thus before the
receive, which happens before the print.
> --
> 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.



--
matt kane
twitter: the_real_mkb / nynexrepublic
http://hydrogenproject.com

Ian Lance Taylor

unread,
May 29, 2014, 10:00:29 AM5/29/14
to liming, golang-nuts
On Thu, May 29, 2014 at 1:32 AM, liming <limi...@gmail.com> wrote:
>
> From go’s documentation
>
> If the channel is unbuffered, the sender blocks until the receiver has
> received the value. If the channel has a buffer, the sender blocks only
> until the value has been copied to the buffer; if the buffer is full, this
> means waiting until some receiver has retrieved a value.
>
> The following code is gaurantined to print “hello, world”
>
> package main
> var c = make(chan int, 10)
> var a string
>
> func f() {
> a = "hello, world"
> c <- 0
> }
>
> func main() {
> go f()
> <-c
> print(a)
> }


Right.


> if we change channel c to unbuffered channel:
>
> package main
> var c = make(chan int)
> var a string
>
> func f() {
> a = "hello, world"
> c <- 0
> }
>
> func main() {
> go f()
> <-c
> print(a)
> }
>
> Is it gaurantined to print “hello, world”

Yes.

> c<-0 will bock until <-c has received the value,
> so c<-0 happens before <-c, as the assignment to a happens before c<-0,
> so in the main function, it will print “hello, world” right?

Right.

> But from go memory model, it says
> A receive from an unbuffered channel happens before the send on that channel
> completes.
>
> so print(a) in main function is not gaurantined to print “hello, world”

No. The memory model also says "A send on a channel happens before
the corresponding receive from that channel completes." So the send
starts to happen, then the receive completes, then the send completes.

Ian

limi...@gmail.com

unread,
May 29, 2014, 10:08:15 PM5/29/14
to golan...@googlegroups.com, limi...@gmail.com
The following rule is specified to buffered channel or both ?

 A send on a channel happens before the corresponding receive from that channel completes.


James Bardin

unread,
May 29, 2014, 10:28:55 PM5/29/14
to golan...@googlegroups.com, limi...@gmail.com
It's been clarified for 1.3

    The kth send on a channel with capacity C happens before the k+Cth receive from that channel completes.

Matt Harden

unread,
May 30, 2014, 8:41:03 PM5/30/14
to James Bardin, golang-nuts, limi...@gmail.com
Hmm, I think that's backwards. It should be "The kth receive on a channel with capacity C happens before the k+Cth send from that channel completes."

... because the receive empties a "slot" in the buffered channel for the send to fill.
Obviously the original wording is correct too, but not very useful.

And the rule that was asked about is still there, and does apply to both buffered and unbuffered channels. The "corresponding receive" is obviously the one that receives the particular item being sent.



--

Dmitry Vyukov

unread,
May 31, 2014, 4:51:55 AM5/31/14
to Matt Harden, James Bardin, golang-nuts, limi...@gmail.com
On Sat, May 31, 2014 at 4:40 AM, Matt Harden <matt....@gmail.com> wrote:
> Hmm, I think that's backwards. It should be "The kth receive on a channel
> with capacity C happens before the k+Cth send from that channel completes."

Ha-ha, it's funny taking into account history of this piece of wording:
https://code.google.com/p/go/issues/detail?id=6242
https://codereview.appspot.com/75130045

However, the original intention was consistent with your wording:
https://code.google.com/p/go/issues/detail?id=6242#c15

I've mailed a patch to fix the doc:
https://codereview.appspot.com/101980047

Thanks for noting this!

threeb...@gmail.com

unread,
Apr 25, 2018, 8:46:33 AM4/25/18
to golang-nuts
So it always guarantees to print "hello world" for the unbuffered channel, doesn't it?

package main
var c = make(chan int)
var a string

func f() {
     a = "hello, world"
     c <- 0
}

func main() {
     go f()
     <-c
     print(a)
it will guarantee to print "hello, world".

package main
var c = make(chan int)
var a string

func f() {
     a = "hello, world"
      <-c
}

func main() {
     go f() 
     c <- 0
     print(a)

it will also guarantee to print "hello, world".

 A send on a channel happens before the corresponding receive from that channel completes.
For the unbuffered channel and the buffered channel.

A receive from an unbuffered channel happens before the send on that channel completes.
Only for the unbuffered channel.


在 2014年5月29日星期四 UTC+8下午10:00:29,Ian Lance Taylor写道:

Ian Lance Taylor

unread,
Apr 25, 2018, 9:49:03 AM4/25/18
to threeb...@gmail.com, golang-nuts
Yes.

Ian
Reply all
Reply to author
Forward
0 new messages