Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >golang 系列:atomic 原子操作

golang 系列:atomic 原子操作

原创
作者头像
lincoln
修改于 2021-08-20 02:33:45
修改于 2021-08-20 02:33:45
1.5K0
举报
文章被收录于专栏:后端后端

sync/atomic 介绍

当我们想要对某个变量并发安全的修改,除了使用官方提供的 mutex,还可以使用 sync/atomic 包的原子操作,它能够保证对变量的读取或修改期间不被其他的协程所影响。

atomic 包的原子操作是通过 CPU 指令,也就是在硬件层次去实现的,性能较好,不需要像 mutex 那样记录很多状态。 当然,mutex 不止是对变量的并发控制,更多的是对代码块的并发控制,2 者侧重点不一样。

sync/atomic 操作

atomic 包有几种原子操作,主要是 Add、CompareAndSwap、Load、Store、Swap。

Add

atomic 的 Add 是针对 int 和 uint 进行原子加值的:

代码语言:txt
AI代码解释
复制
func AddInt32(addr *int32, delta int32) (new int32)
func AddUint32(addr *uint32, delta uint32) (new uint32)
func AddInt64(addr *int64, delta int64) (new int64)
func AddUint64(addr *uint64, delta uint64) (new uint64)
func AddUintptr(addr *uintptr, delta uintptr) (new uintptr)

CompareAndSwap

比较并交换方法实现了类似乐观锁的功能,只有原来的值和传入的 old 值一样,才会去修改:

代码语言:txt
AI代码解释
复制
func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)
func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)
func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)
func CompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool)
func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool)
func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)

需要注意的是,CompareAndSwap 有可能产生 ABA 现象发生。也就是原来的值是 A,后面被修改 B,再后面修改为 A。在这种情况下也符合了 CompareAndSwap 规则,即使中途有被改动过。

Load

Load 方法是为了防止在读取过程中,有其他协程发起修改动作,影响了读取结果,常用于配置项的整个读取。

代码语言:txt
AI代码解释
复制
func LoadInt32(addr *int32) (val int32)
func LoadInt64(addr *int64) (val int64)
func LoadUint32(addr *uint32) (val uint32)
func LoadUint64(addr *uint64) (val uint64)
func LoadUintptr(addr *uintptr) (val uintptr)
func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)

Store

有原子读取,就有原子修改值,前面提到过的 Add 只适用于 int、uint 类型的增减,并没有其他类型的修改,而 Sotre 方法通过 unsafe.Pointer 指针原子修改,来达到了对其他类型的修改。

代码语言:txt
AI代码解释
复制
func StoreInt32(addr *int32, val int32)
func StoreInt64(addr *int64, val int64)
func StoreUint32(addr *uint32, val uint32)
func StoreUint64(addr *uint64, val uint64)
func StoreUintptr(addr *uintptr, val uintptr)
func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer)

Swap

Swap 方法实现了对值的原子交换,不仅 int,uint 可以交换,指针也可以。

代码语言:txt
AI代码解释
复制
func SwapInt32(addr *int32, new int32) (old int32)
func SwapInt64(addr *int64, new int64) (old int64)
func SwapUint32(addr *uint32, new uint32) (old uint32)
func SwapUint64(addr *uint64, new uint64) (old uint64)
func SwapUintptr(addr *uintptr, new uintptr) (old uintptr)
func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer)

总结

atomic 很多时候可能都没有使用上,毕竟 mutex 的拓展性比较好,使用起来也比较友好。但这并不妨碍我们对极致性能的追求,有时候,细节决定了性能!


感兴趣的朋友可以搜一搜公众号「 阅新技术 」,关注更多的推送文章。

可以的话,就顺便点个赞、留个言、分享下,感谢各位支持!

阅新技术,阅读更多的新知识。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Golang 语言标准库 sync/atomic 包原子操作
我们已经介绍过 Mutex、RWMutex 等并发原语操作,如果您还没有阅读,请查看文末「推荐阅读」列表。
frank.
2020/12/22
7440
深入理解Golang的atomic原子操作
Golang的atomic包提供了一组原子操作函数,用于在多个goroutine之间安全地访问和修改共享变量。这些原子操作函数可以保证对共享变量的操作原子性的,从而避免了竞态条件的发生。本文将深入探讨Golang的atomic包的原子操作。
KunkkaWu
2023/06/02
2.6K0
深入理解Golang的atomic原子操作
【并发编程】atomic 如何保证原子操作?分别用那几个方法?
之前学习了一些并发原语,已经认为差不多可以应对很多场景了,但是为什么还要学习原子操作呢?原来,在一些场景中,使用并发原语可能更加复杂,为了更轻松地实现底层的优化。
了凡银河系
2022/08/22
1.2K0
Go并发之atomic
sync/atomic包提供了原子操作的能力,直接有底层CPU硬件支持,因而一般要比基于操作系统API的锁方式效率高些;这些功能需要非常小心才能正确使用。 除特殊的底层应用程序外,同步更适合使用channel或sync包的功能。 通过消息共享内存; 不要通过共享内存进行通信。
灰子学技术
2020/06/09
7270
【Go】sync.atomic
这一类方法的作用是拿 addr 上的值和 old 比较,如果相等,就把 new 存储到 addr。
JuneBao
2022/10/26
4850
Go语言中的sync/atomic包详解
sync/atomic包提供了一组函数用于原子性的操作类型安全的值。这些函数为低级并发应用程序提供了必要的原子操作。它包括一些函数,用于操作内存中的值,这些操作是不可分割的,也就是说,在操作执行过程中,不会被其他goroutine中断。这一点非常重要,因为在并发编程中,我们常常需要保证某些操作的原子性,以防止出现数据竞争等问题。
运维开发王义杰
2023/08/10
9310
Go语言中的sync/atomic包详解
盘点Golang并发那些事儿之二
上一节提到,golang中直接使用关键字go创建goroutine,无法满足我们的需求。主要问题如下
PayneWu
2021/06/10
5160
盘点Golang并发那些事儿之二
《GO并发编程实战》—— 原子操作
我们已经知道,原子操作即是进行过程中不能被中断的操作。也就是说,针对某个值的原子操作在被进行的过程当中,CPU绝不会再去进行其它的针对该值的操作。无论这些其它的操作是否为原子操作都会是这样。为了实现这样的严谨性,原子操作仅会由一个独立的CPU指令代表和完成。只有这样才能够在并发环境下保证原子操作的绝对安全。 Go语言提供的原子操作都是非侵入式的。它们由标准库代码包sync/atomic中的众多函数代表。我们可以通过调用这些函数对几种简单的类型的值进行原子操作。这些类型包括int32、int64、uint32
李海彬
2018/03/27
1.3K0
go-并发
Go语言的并发通过 goroutine 实现。 goroutine 类似于线程,属于用户态的线程,我们可以根据需要创建成千上万个 goroutine 并发工作。 goroutine 是由Go语言的运行时(runtine)调度完成,而线程是由操作系统调度完成的。
新人小试
2020/03/27
7220
go-并发
手摸手Go 并发编程基石atomic
“高并发 高性能 高可用”一直以来作为搬砖界用力搬砖的口号。由于CPU一次读取存储数据的长度有限,比如32bit的平台修改int64需要被拆分成两次写操作,更何况对于结构体的赋值,那么对于高并发场景下我们怎么才能保证数据的完整性和一致性呢?
用户3904122
2022/06/29
6240
详解并发编程基础之原子操作(atomic包)
原子(atomic)本意是"不能被进一步分割的最小粒子",而原子操作(atomic operation)意为"不可中断的一个或一系列操作"。其实用大白话说出来就是让多个线程对同一块内存的操作是串行的,不会因为并发操作把内存写的不符合预期。我们来看这样一个例子:假设现在是一个银行账户系统,用户A想要自己从自己的账户中转1万元到用户B的账户上,直到转帐成功完成一个事务,主要做这两件事:
Golang梦工厂
2022/07/08
3780
Golang 五种原子性操作的用法详解
本文我们详细聊一下Go语言的原子操作的用法,啥是原子操作呢?顾名思义,原子操作就是具备原子性的操作... 是不是感觉说了跟没说一样,原子性的解释如下:
KevinYan
2021/09/24
3.8K1
原子操作和互斥锁的区别
这个系列的文章里介绍了很多并发编程里经常用到的技术,除了Context、计时器、互斥锁还有通道外还有一种技术--原子操作在一些同步算法中会被用到。今天的文章里我们会简单了解一下Go语言里对原子操作的支持,然后探讨一下原子操作和互斥锁的区别。
KevinYan
2020/06/16
4.7K0
2.Go语言之标准库学习记录(2)
描述: Go语言中strconv包实现了基本数据类型和其字符串表示的相互转换,主要可以将字符串类型转换为整型(int32 、int64、int、uint)、浮点型(float32、float64)、布尔型(Boolean)等。
全栈工程师修炼指南
2022/09/29
5160
原子操作atomic包学习
本文我们来学习Go的atomic包,对于atomic包使用和原理比较熟悉的同学本文就可以不用看了😁。下面我们从atomic是什么,提供给我们了哪些接口,为什么有atomic包以及它的实现几个角度来学习它。 atomic有哪些内容 atomic是Go中sync下的一个package,它实现了同步算法底层的原子的内存操作原语,提供了一套原子操作的方法接口。 高级语言的一个语句对应到CPU层面往往都是多条指令,CPU一次只能执行一条指令。例如C语言中的i++操作,对应到CPU层面是3条指令:第一步将i的执行从内
数据小冰
2022/08/15
1.4K0
原子操作atomic包学习
听GPT 讲Go源代码--types.go
types.go文件是Golang运行时包(runtime)中的一个文件,它定义了运行时所需的各种类型。该文件中定义了一些重要的类型,比如:String、Bool、Int、Float、Map、Slice、Chan等类型。这些类型是Golang程序运行时所需的基本类型,它们是由运行时系统处理和管理的。
fliter
2023/09/05
2970
听GPT 讲Go源代码--types.go
golang源码分析(31)
针对Golang 1.9的sync.WaitGroup进行分析,与Golang 1.10基本一样除了将panic改为了throw之外其他的都一样。源代码位置:sync\waitgroup.go。
golangLeetcode
2022/08/02
3280
手摸手Go 也谈sync.WaitGroup
最近因为工作上的事情更新会相对有点儿慢,这周末又加了天班。然后昨天好好休息了下,顺便翻了下《云雀叫了一整天》,看到一首小诗觉得不错分享给大家。
用户3904122
2022/06/29
5070
手摸手Go 也谈sync.WaitGroup
golang 系列:waitgroup 解析
Golang 提供了简洁的 go 关键字来让开发者更容易的进行并发编程,同时也提供了 WaitGroup 对象来辅助并发控制。今天我们就来分析下 WaitGroup 的使用方法,顺便瞧一瞧它的底层源码。
lincoln
2021/08/15
7110
2022-06-18:golang与 C++数据结构类型对应关系是怎样的?
uintptr和unsafe.Pointer相当于c++的void*,也就是任意指针。
福大大架构师每日一题
2023/06/08
2450
2022-06-18:golang与 C++数据结构类型对应关系是怎样的?
相关推荐
Golang 语言标准库 sync/atomic 包原子操作
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档