网站首页 > 博客文章 正文
在Go语言中,原子操作可以用来保证并发安全,避免竞争条件。Go语言中提供了sync/atomic标准库来支持原子操作。下面是一些常见的原子操作的示例。
原子加
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var count int32
var wg sync.WaitGroup
wg.Add(100)
for i := 0; i < 100; i++ {
go func() {
atomic.AddInt32(&count, 1)
wg.Done()
}()
}
wg.Wait()
fmt.Println("Count:", count)
}
在这个例子中,我们创建了一个int32类型的变量count,然后启动了100个goroutine,每个goroutine执行一次原子加操作atomic.AddInt32(&count, 1)。最终输出count的值,可以看到结果是100,说明原子加操作是并发安全的。
原子比较并交换
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var count int32
var wg sync.WaitGroup
wg.Add(100)
for i := 0; i < 100; i++ {
go func() {
old := count
for !atomic.CompareAndSwapInt32(&count, old, old+1) {
old = count
}
wg.Done()
}()
}
wg.Wait()
fmt.Println("Count:", count)
}
在这个例子中,我们同样创建了一个int32类型的变量count,然后启动了100个goroutine,每个goroutine执行一次原子比较并交换操作atomic.CompareAndSwapInt32(&count, old, old+1)。在这个操作中,首先获取当前count的值,并将其保存在old变量中,然后调用atomic.CompareAndSwapInt32()方法,如果count的值等于old,则将count的值更新为old+1,否则不更新。如果更新失败,则重新获取count的值,继续执行比较并交换操作。最终输出count的值,可以看到结果是100,说明原子比较并交换操作也是并发安全的。
原子加载和存储
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var count int32
var wg sync.WaitGroup
wg.Add(2)
go func() {
for {
val := atomic.LoadInt32(&count)
fmt.Println("Read count:", val)
if val >= 10 {
wg.Done()
return
}
}
}()
go func() {
for i := 0; i < 10; i++ {
atomic.StoreInt32(&count, int32(i))
fmt.Println("Write count:", i)
}
wg.Done()
}()
wg.Wait()
fmt.Println("Done")
}
在这个例子中,我们创建了一个int32类型的变量count,然后启动了两个goroutine。第一个goroutine不断地读取count的值,如果count的值大于等于10,则退出循环。第二个goroutine执行10次原子存储操作atomic.StoreInt32(&count, int32(i)),将count的值更新为0到9之间的整数。最终输出Done,说明程序正常结束。
以上是一些常见的原子操作的示例,这些操作可以用来保证并发安全,避免竞争条件。需要注意的是,使用原子操作并不意味着程序就是正确的,还需要注意竞争条件的发生时机和条件。
原子操作和加锁的区别
原子操作和加锁都是保证并发安全的机制,但它们有一些不同的特点和应用场景。
- 原子操作
原子操作是一种非常轻量级的同步机制,它是基于硬件层面的支持,能够保证单个操作的原子性,不需要像加锁那样进行上下文切换和操作系统调度,因此具有非常高的性能。原子操作适用于处理简单的数据结构,例如整型、指针等,能够保证数据的一致性和可见性,但是无法处理复杂的数据结构,例如链表、哈希表等。
- 加锁
加锁是一种更加通用的同步机制,它能够保证在同一时刻只有一个goroutine可以访问共享资源,从而避免竞争条件。加锁的实现通常需要进行上下文切换和操作系统调度,因此相对于原子操作,性能较低。加锁适用于处理复杂的数据结构和共享资源,例如链表、哈希表等。
另外,需要注意的是,使用原子操作并不能完全替代加锁,因为在一些情况下需要对多个变量进行操作,并且保证这些操作的原子性和可见性,这时候就需要使用加锁。在实际应用中,需要根据具体的场景和需求来选择使用原子操作还是加锁。
猜你喜欢
- 2024-09-26 “全栈2019”Java原子操作第十一章:CAS与ABA问题介绍及解决方案
- 2024-09-26 从CAS讲起,真正高性能解决并发编程的原子操作
- 2024-09-26 “全栈2019”Java原子操作第九章:atomic包下原子数组介绍与使用
- 2024-09-26 “全栈2019”Java原子操作第九章:atomic包下原子数组简单介绍
- 2024-09-26 “全栈2019”Java原子操作第十一章:CAS与ABA问题介绍与探讨
- 2024-09-26 CAS原子操作实现无锁及性能分析(cas能保证原子性吗)
- 2024-09-26 面试必备:Java 原子操作的实现原理「精品长文」
- 2024-09-26 java的原子操作和原子操作的好处(java原子类的使用场景)
- 2024-09-26 原子操作&普通锁&读写锁原理讲解
- 2024-09-26 并发编程 --- CAS原子操作(cas cpu原语)
你 发表评论:
欢迎- 最近发表
-
- 给3D Slicer添加Python第三方插件库
- Python自动化——pytest常用插件详解
- Pycharm下安装MicroPython Tools插件(ESP32开发板)
- IntelliJ IDEA 2025.1.3 发布(idea 2020)
- IDEA+Continue插件+DeepSeek:开发者效率飙升的「三体组合」!
- Cursor:提升Python开发效率的必备IDE及插件安装指南
- 日本旅行时想借厕所、买香烟怎么办?便利商店里能解决大问题!
- 11天!日本史上最长黄金周来了!旅游万金句总结!
- 北川景子&DAIGO缘定1.11 召开记者会宣布结婚
- PIKO‘PPAP’ 洗脑歌登上美国告示牌
- 标签列表
-
- ifneq (61)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)