英文:
Why supporting atomic.Load and atomic.Store in Go?
问题
我认为atomic.Load(addr)应该等于*addr,atomic.Store(addr, newval)应该等于*addr = newval。那么为什么使用*addr或*addr = newval不是原子操作呢?我的意思是它们最终会被解释为只有一条CPU指令(即原子操作)吧?
英文:
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)?
答案1
得分: 5
由于排序保证和内存操作的可见性。例如:
y:=0
x:=0
x=1
y=1
在上面的程序中,另一个goroutine可以看到x和y的值为(0,0)、(0,1)、(1,0)或(1,1)。这是因为编译器重新排序代码、编译器优化或硬件级别的内存操作重新排序。然而:
y:=0
x:=0
x:=1
atomic.StoreInt64(&y,1)
如果另一个goroutine看到atomic.LoadInt64(&y)==1,那么这个goroutine可以保证看到x=1。
另一个例子是忙等待。下面的例子来自Go内存模型:
var a string
var done bool
func setup() {
	a = "hello, world"
	done = true
}
func main() {
	go setup()
	for !done {
	}
	print(a)
}
这个程序不能保证终止,因为main函数中的for循环不能保证看到done=true的赋值。程序可能无限运行,可能打印空字符串,也可能打印"hello, world"。
将done=true替换为原子存储,并将for循环中的检查替换为原子加载,可以保证程序始终完成并打印"hello, world"。
关于这些内容的权威文档是Go内存模型:
英文:
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:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论