当前位置: 首页 > news >正文

Golang中的CAS操作

CAS(Compare And Swap)算法在Go语言中是作为原子操作提供的。CAS是一种无锁的技术,当多个线程尝试使用共享数据时,CAS能够检测到其他线程是否已经改变了这个数据,这是一种解决并发问题的策略。

CAS算法包含三个参数——一个内存位置,一个预期的旧值和一个新值。CAS操作会检查内存位置的当前值与预期的旧值是否相等。如果相等,它就将内存位置的值更新为新值;否则,不进行任何操作。这一操作是原子性的,多线程环境下不会被中断。示意流程如下:

  1. 检查内存位置的当前值是否与期望的原值相等。
  2. 如果相等,那么将这个位置的值更新为新值。这个比较和替换是在一个不可中断的操作中完成的。
  3. 如果不相等,那么不做任何操作。

在 Go 语言中,可以使用 sync/atomic 包中的原子操作函数来实现 CAS 操作。下面是一些常见的原子操作函数:

  • atomic.CompareAndSwapInt32(addr *int32, old, new int32) bool
  • atomic.CompareAndSwapInt64(addr *int64, old, new int64) bool
  • atomic.CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) bool
  • atomic.CompareAndSwapUint32(addr *uint32, old, new uint32) bool
  • atomic.CompareAndSwapUint64(addr *uint64, old, new uint64) bool

下面是一个在多线程环境下的简单用法示例:

package mainimport ("fmt""sync""sync/atomic"
)type Counter struct {value int32
}func (c *Counter) Increment() {for {oldValue := atomic.LoadInt32(&c.value)newValue := oldValue + 1if atomic.CompareAndSwapInt32(&c.value, oldValue, newValue) {return}}
}func (c *Counter) Value() int32 {return atomic.LoadInt32(&c.value)
}func main() {var wg sync.WaitGroupcounter := Counter{}for i := 0; i < 100; i++ {wg.Add(1)go func() {defer wg.Done()counter.Increment()}()}wg.Wait()fmt.Println("Final counter value:", counter.Value())
}

在这个示例中,我们定义了一个 Counter 结构体,其中包含一个 int32 类型的 value 字段。Increment 方法使用 CAS 操作来安全地增加计数器的值。如果 CompareAndSwapInt32 操作失败(因为 value 已被其他 goroutine 修改),循环会重新尝试,直到操作成功。这样就保证了计数器在多线程环境下的安全性。

实际操作中,CAS操作的正确性依赖于预期值和实际值的结果对比,因为在设计算法的过程中需要仔细考虑可能的竞争条件。

最后给大家推荐一个LinuxC/C++高级架构系统教程的学习资源与课程,可以帮助你有方向、更细致地学习C/C++后端开发,具体内容请见 https://xxetb.xetslk.com/s/1o04uB

相关文章:

  • 算法训练营第六十七天 | 卡码网110 字符串接龙、卡码网105 有向图的完全可达性、卡码网106 岛屿的周长
  • 【操作系统】第五章 文件系统
  • odoo的采购询价单,默认情况下显示‘draft‘,‘sent‘,‘purchase‘,请问什么情况下才会显示‘to approve‘?
  • clean code-代码整洁之道 阅读笔记(第十一章)
  • 静态ip详解
  • Android面试题精选——再聊Android-Handler机制
  • 分类接口开发
  • [SAP ABAP] 排序内表数据
  • 计组--存储系统--复习专用...
  • 【iOS】#include、#import、@class、@import
  • 2024广东省职业技能大赛云计算赛项实战——Minio服务搭建
  • CTFHUB-SSRF-端口扫描
  • DDMA信号处理以及数据处理的流程---cfar检测
  • 【database3】oracle:数据交换/存储/收集
  • Vite: 关于静态资源的处理机制
  • express + mock 让前后台并行开发
  • Java IO学习笔记一
  • java2019面试题北京
  • Mithril.js 入门介绍
  • python学习笔记-类对象的信息
  • scala基础语法(二)
  • uva 10370 Above Average
  • 从零开始学习部署
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 聚类分析——Kmeans
  • 微服务核心架构梳理
  • 微服务框架lagom
  • 消息队列系列二(IOT中消息队列的应用)
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • [Shell 脚本] 备份网站文件至OSS服务(纯shell脚本无sdk) ...
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • #QT(TCP网络编程-服务端)
  • (3)nginx 配置(nginx.conf)
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (四)Linux Shell编程——输入输出重定向
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • .net与java建立WebService再互相调用
  • .xml 下拉列表_RecyclerView嵌套recyclerview实现二级下拉列表,包含自定义IOS对话框...
  • [].slice.call()将类数组转化为真正的数组
  • [2016.7 Day.4] T1 游戏 [正解:二分图 偏解:奇葩贪心+模拟?(不知如何称呼不过居然比std还快)]
  • [AI aider] 打造终端AI搭档:Aider让编程更智能更有趣!
  • [Angular 基础] - 数据绑定(databinding)
  • [C#]winform部署yolov9的onnx模型
  • [CERC2017]Cumulative Code
  • [codevs1288] 埃及分数