一、atomic包与原子操作
atomic包是Go语言提供的原子操作(atomic operation)原语的相关接口。原子操作是相对于普通指令操作而言的。以一个整型变量自增的语句为例:
var i int
i++
i++这行语句需要以下3条普通机器指令来完成变量i的自增。
LOAD:将变量从内存加载到CPU寄存器。
ADD:执行加法指令。
STORE:将结果存储回原内存地址。
这3条普通指令在执行过程中是可中断的。而原子操作的指令是不可中断的,它就好比一个事务,要么不执行,一旦执行就一次性全部执行完毕,不可分割。
正因如此,原子操作可用于共享数据的并发同步。
二、i++ 100次在并发与非并发为什么得到了不同的值
func TestI100(t *testing.T) {
sum := 0
for i := 0; i < 100; i++ {
sum += i
}
t.Log(sum) //sum = 4950
}
func TestGoroutineI100(t *testing.T) {
sum := 0
for i := 0; i < 100; i++ {
go func(j int) {
sum += j
}(i)
}
t.Log(sum) //sum = 2421
}
func TestAtomicI100(t *testing.T) {
var sum int32
for i := 0; i < 100; i++ {
go func(j int) {
atomic.AddInt32(&sum, int32(j))
}(i)
}
t.Log(sum) //4278
}
sum的正确值是 4950,TestGoroutineI100() 为啥错误?
并发的情况下,不同的协程goroutine同时拿到一个 sum值,然后执行 += 此时就会出现上面的问题。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。