Reputation: 193
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
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:
Upvotes: 5