英文:
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:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论