On Monday, 12 September 2016 12:04:30 UTC-4, sqweek E. wrote:
>
> Yes, through plain assignment. What problems arise from that?
>

Here's the general form of the problem.  In the code below, one goroutine 
(f) creates a variable, initializes it (x=1), then shares its address with 
another goroutine (in this case by assigning to a global variable, but 
that's a detail).  Another goroutine (g) reads the pointer out of the 
global variable and inspects the variable to which it points.

type T struct { x int }

var global *T

func f() {
    p := new(T)
    p.x = 1
    global = p // "publish" the new T (racy!)
}

func g() {
    p = global
    if p != nil {
        println(p.x) // may print "0" due to data race
    }
}

go f()
go g()

One might naively think that the print statement always prints 1, but in 
fact it can print 0.  The reason is that the compiler or CPU is free to 
reorder the assignments p.x=1 and global=p, since f can't tell.  But 
reordering means other goroutines might observe a non-nil pointer in global 
before the thing it points to has been fully initialized.

To safely "publish" a variable initialized by one goroutine so that other 
goroutines see it properly initialized, you need "barrier semantics", that 
is, you need to tell the compiler and CPU not to reorder those assignments. 
That's what atomic.Value does.

But you shouldn't reach for atomic.Value without data.  In most programs, a 
mutex is simpler to reason about and plenty fast enough.

-- 
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