在并发操作中,原子操作是非常现实的问题,典型的就是多个 CPU 对同一个内存的值进行操作,如 i++,很可能两次 i++,这个 i 只增加了一次,sync/atomic 就是为了解决这个问题的。具体的实现在不同的操作系统的实现是不同的, Intel 的 CPU 架构机器上,主要是使用总线锁的方式实现的。 在 AMD 的 CPU 架构机器上就是使用 MESI 一致性协议的方式来保证原子操作。
Atomic 提供了对简单类型进行操作,这些类型包括 int32, int64, uint32, uint64, uintptr, unsafe.Pointer 共6个。这些函数的原子操作共有5种:增或减,比较并交换、载入、存储和交换
如,当我们不使用原子操作的时候:
package main
import (
strconv
)
var num int64
func main() {
num = 0
ch := make(chan string)
for i := 0; i < 10000; i++ {
go add(ch, i)
}
for i := 0; i < 10000; i++ {
<-ch
}
println(num)
}
func add(ch chan string, i int) {
num++
ch <- (add + strconv.Itoa(i))
}
多次运行,最终得到的 num 值是不同的:
按照代码逻辑应该是需要为 10000 则是符合预期的,更改使用原子操作时,将 num++ 改为 atomic.AddInt64(&num, 1)
package main
import (
strconv
sync/atomic
)
var num int64
func main() {
num = 0
ch := make(chan string)
for i := 0; i < 10000; i++ {
go add(ch, i)
}
for i := 0; i < 10000; i++ {
<-ch
}
println(num)
}
func add(ch chan string, i int) {
atomic.AddInt64(&num, 1)
ch <- (add + strconv.Itoa(i))
}
这个时候是符合预期的
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
请登录后查看评论内容