Golang 学习笔记:Golang 的 sync/atomic 原子操作
在并发操作中,原子操作是非常现实的问题,典型的就是多个 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)) }
这个时候是符合预期的
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论