sync/atomic包提供了底层的原子级内存操作,其执行过程不能被中断,这也就保证了同一时刻一个线程的执行不会被其他线程中断,也保证了多线程下数据操作的一致性。
操作的数据类型共有六种:int32, int64, uint32, uint64, uintptr, unsafe.Pinter,每一种类型又提供了五种操作:Add增减, CompareAndSwap比较并交换, Swap交换, Load载入, Store存储。
函数名以"操作+类型"组合而来。例如AddInt32/AddUint64/LoadInt32/LoadUint64...

以Int32为例:

// AddInt32 atomically adds delta to *addr and returns the new value.
func AddInt32(addr *int32, delta int32) (new int32)
AddInt32可以实现对元素的原子增加或减少,函数会直接在传递的地址上进行修改操作。
addr需要修改的变量的地址,delta修改的差值[正或负数],返回new修改之后的新值。

var a int32
a += 10
atomic.AddInt32(&a, 10)
fmt.Println(a == 20) // true//需要注意的是如果是uint32,unint64时,不能直接传负数,所以需要利用二进制补码机制
var b uint32
b += 20
atomic.AddUint32(&b, ^uint32(10-1)) // 等价于 b -= 10
// atomic.Adduint32(&b, ^uint32(N-1)) //N为需要减少的正整数值
fmt.Println(b == 10) // true

// CompareAndSwapInt32 executes the compare-and-swap operation for an int32 value.
func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)
函数会先判断参数addr指向的值与参数old是否相等,如果相等,则用参数new替换参数addr的值。最后返回swapped是否替换成功。

package main
import ("fmt""sync""sync/atomic"
)
func main() {var c int32wg := sync.WaitGroup{}//开启100个goroutinefor i := 0; i < 100; i++ {wg.Add(1)go func() {defer wg.Done()tmp := atomic.LoadInt32(&c)if !atomic.CompareAndSwapInt32(&c, tmp, tmp+1) {fmt.Println("c 修改失败")}}()}wg.Wait()//c的值有可能不等于100,频繁修改变量值情况下,CompareAndSwap操作有可能不成功。fmt.Println("c : ", c)
}
偶尔输出:
//c 修改失败
//c :  99
多数情况下输出
//c :  100

// SwapInt32 atomically stores new into *addr and returns the previous *addr value.
func SwapInt32(addr *int32, new int32) (old int32)
Swap会直接执行赋值操作,并将原值作为返回值返回

package main
import ("fmt""sync""sync/atomic"
)
func main() {var e int32wg2 := sync.WaitGroup{}//开启10个goroutinefor i := 0; i < 10; i++ {wg2.Add(1)go func() {defer wg2.Done()tmp := atomic.LoadInt32(&e)old := atomic.SwapInt32(&e, tmp + 1)fmt.Println("e old : ", old)}()}wg2.Wait()fmt.Println("e : ", e)
}// e old :  3
// e old :  1
// e old :  2
// e old :  4
// e old :  5
// e old :  6
// e old :  7
// e old :  8
// e old :  9
// e old :  0
// e :  10

// LoadInt32 atomically loads *addr.
func LoadInt32(addr *int32) (val int32)
Load函数参数为需要读取的变量地址,返回值为读取的值
Load和Store操作对应与变量的原子性读写,许多变量的读写无法在一个时钟周期内完成,而此时执行可能会被调度到其他线程,无法保证并发安全。Load只保证读取的不是正在写入的值,Store只保证写入是原子操作。所以在使用的时候要注意。

// StoreInt32 atomically stores val into *addr.
func StoreInt32(addr *int32, val int32)
Store函数参数为需要存储的变量地址及需要写入的值,存储某个值时,任何CPU都不会对该值进行读或写操作,存储操作总会成功,它不关心旧值是什么,与CompareAndSwap不同

var d int32
fmt.Println("d : ", d)
atomic.StoreInt32(&d, 666)
fmt.Println("d : ", d)

文章来源于 https://www.lixiaocheng.com/read/704

Go原子操作 sync/atomic相关推荐

  1. 原子操作之sync/atomic

    2019独角兽企业重金招聘Python工程师标准>>> 原子操作之sync/atomic 对于并发操作而言,原子操作是个非常现实的问题.典型的就是i++的问题. 当两个CPU同时对内 ...

  2. Golang 中 sync/atomic 包的原子操作

    背景 Go中多协程的情况下, 要保证操作的原子性,一般要使用RWMutex或者Mutex, 但是锁使用起来比较复杂,还要考虑lock 和unlock 顺序和成对出现,不注意就容易出错. 于是在sync ...

  3. sync/atomic 库使用小结

    sync/atomic 库提供了原子操作的支持,原子操作直接有底层CPU硬件支持,因而一般要比基于操作系统API的锁方式效率高些.本文对 sync/atomic 中的基本操作进行一个简单的介绍. 原子 ...

  4. Go 学习笔记(23)— 并发(02)[竞争,锁资源,原子函数sync/atomic、互斥锁sync.Mutex]

    本文参考 <Go 语言实战> 1. 竞争状态简述 如果两个或者多个 goroutine 在没有互相同步的情况下,访问某个共享的资源,并试图同时读和写这个资源,就处于相互竞争的状态,这种情况 ...

  5. 原子(atom)本意是“不能被进一步分割的最小粒子”,而原子操作(atomic operation)

    1. 引言 原子(atom)本意是"不能被进一步分割的最小粒子",而原子操作(atomic operation)意为"不可被中断的一个或一系列操作" .在多处理 ...

  6. 原子操作(atomic operation)

    深入分析Volatile的实现原理 引言 在多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatile是轻量级的synchronized,它在多处理器开发中保证了共 ...

  7. linux c/c++ 原子操作库 atomic atomic_flag 简介

    目录 简介 1.类classes 1.1 atomic 1)构造函数 2)赋值运算 3)is_lock_free 4)store 5)load 6)operator T 7)exchange 8)co ...

  8. 探究Java如何实现原子操作(atomic operation)

    1. 让我们首先了解下java 中 Volatile 关键字 Volatile可实现java内存模型当中的可见性, java内存模型的可见性: 可见性,是指线程之间的可见性,一个线程修改的状态对另一个 ...

  9. 【C++】原子操作(atomic)与无锁编程学习记录

    lambda std::bind 智能指针使用 深度库基于数据结构与算法的优化 atomic 操作与多线程 数据安全 原子内存操作 设计模式:单例模式 C++11原子操作与无锁编程 https://w ...

最新文章

  1. kaptcha验证码实现,配合spring boot使用
  2. 可覆写的函数与创建节点
  3. 运营商部署4.5G热情高涨:将影响5G商用
  4. jQuery-对Select的操作集合
  5. git 删除已经 add 的文件
  6. Redis 基本命令、键(key)命令、基本数据类型(命令行操作)
  7. 软件项目管理 问答题
  8. sub求阶乘c语言,用VB编写程序求S=A!+B!+C!,要求阶乘的计算使用Sub过程来实现,参数A、B、C的值从键盘输入的程序代码?...
  9. MS-DOS虚拟机安装
  10. 基于asp.net的在线问卷调查系统
  11. 6亿融资,今麦郎有底气上市吗?
  12. 中国网络游戏未来发展方向
  13. HAOI2017 简要题解
  14. 发送验证码-整合阿里云短信服务功能与电子邮箱通知功能
  15. (无任何网络配置,纯代码实现) 一个组件,一个hook,让你在本地开发环境中拿到微信code
  16. 【UE4 第一人称射击游戏】12-全自动步枪并显示剩余弹药量
  17. ps怎么修改图片上的数字(适用于图片上已有的数字)
  18. 夏日炎炎,使用决策树去挑选西瓜(python实现)
  19. “阿法狗”之父:关于围棋,人类3000年来犯了一个错!
  20. pycharm one dark主题设置及下载

热门文章

  1. Kafka如何更新元数据到各broker节点
  2. Java零基础入门 :(1) windows7 配置Java环境变量
  3. FastJson PropertyNamingStrategy 转换成JSON字符串的四种格式配置及源码解析
  4. linux目录自动同步,Linux下rsync+inotify实现实时文件自动同步
  5. 临界区设计太大或太小有何缺点_冷库风冷冷凝器和水冷冷凝器区别及优缺点比较...
  6. 哈工大人工智能作业一_想从事人工智能行业,考研选什么专业对口?
  7. 图解浏览器缓存,教你提高用户体验
  8. java mail 接受QQ邮箱未读的邮件
  9. Python数据科学|第一章:数据科学家的武器库
  10. 在windows server 2008 R2上运行disk cleanup