Markity
Markity

Reputation: 193

Why supporting atomic.Load and atomic.Store in Go?

I think atomic.Load(addr) should equal *addr and atomic.Store(addr, newval) should equal *addr = newval. So why doing so(using *addr or *addr = newval) is not a atomic operation? I mean they will eventually be interpreted to be just one cpu instruction(which is atomic)?

Upvotes: 1

Views: 385

Answers (1)

Burak Serdar
Burak Serdar

Reputation: 51582

Because of ordering guarantees, and memory operation visibility. For instance:

y:=0
x:=0
x=1
y=1

In the above program, another goroutine can see (0,0), (0,1), (1,0), or (1,1) for x and y. This is because of compiler reordering the code, compiler optimization,s or because of memory operation reordering at the hardware level. However:

y:=0
x:=0
x:=1
atomic.StoreInt64(&y,1)

If another goroutine sees atomic.LoadInt64(&y)==1, then the goroutine is guaranteed to see x=1.

Another example is the busy-waiting. The following example is from the go memory model:

var a string
var done bool

func setup() {
    a = "hello, world"
    done = true
}

func main() {
    go setup()
    for !done {
    }
    print(a)
}

This program is not guaranteed to terminate, because the for-loop in main is not guaranteed to see the done=true assignment. The program may run indefinitely, may print empty string, or it may print "hello, world".

Replacing done=true with an atomic store, and the check in the for-loop with an atomic load guarantees that the program always finishes and prints "hello, world".

The authoritative document about these is the go memory model:

https://go.dev/ref/mem

Upvotes: 5

Related Questions