并发编程 --- CAS原子操作
介绍
CAS(Compare And Swap) 是一种无锁算法的实现手段,中文名称为比较并交换。它由 CPU 的原子指令实现,可以在多线程环境下实现无锁的数据结构。
原理
CAS 的原理是:它会先比较内存中的某个值是否和预期值相同,如果相同则更新这个值,否则不做任何操作。这整个过程是原子的,所以可以在多线程环境下实现无锁的数据结构。
CAS 操作有3个原子性操作:
- 读取内存的值
- 将内存的值与期望值比较
- 如果相等,则将内存值更新为新值
这三个操作一起完成,中间不会被线程切换打断。这就保证了比较和交换的原子性。
使用C#伪代码实现如下:
bool Cas(ref object obj, object expected, object newValue)
{
object oldValue = obj;
if (oldValue == expected) {
obj = newValue;
return true;
}
return false;
}
解释如下:
- C#使用ref关键字来表示要操作的内存地址obj
- oldValue = obj读取内存值,obj = newValue更新内存值。
- 其他逻辑与伪代码相同,先读取内存值oldValue,然后判断是否等于期望值expected,如果相等则更新内存值为newValue并返回true,否则返回false。
- CAS操作包含读内存值、比较内存值与期望值、更新内存值三个原子步骤。这三步作为一个整体执行,中间不会被中断,保证比较和交换的原子性。
- 该方法尝试使用CAS操作更新obj的值,当且仅当obj的值等于expected时才更新,否则不做任何操作。
示例
C# 中提供了 Interlocked 类来实现 CAS 操作。主要包含以下几个方法:
- Interlocked.CompareExchange(ref val, newValue, comparand):如果
val等于comparand,则将val的值更新为newValue,并返回comparand,否则返回val的当前值。 - Interlocked.Exchange(ref val, newValue):将
val的值更新为newValue,并返回val的旧值。 - Interlocked.Increment(ref val):将
val的值增加 1,并返回增加后的值。 - Interlocked.Decrement(ref val):将
val的值减少 1,并返回减少后的值。
示例代码:
int val = 0;
Interlocked.CompareExchange(ref val, 1, 0); // val = 1, 返回 0
Interlocked.CompareExchange(ref val, 2, 0); // val 保持 1, 返回 1
Interlocked.Increment(ref val); // val = 2, 返回 2
Interlocked.Decrement(ref val); // val = 1, 返回 1
这些方法可以实现无锁数据结构,例如无锁队列,示例为伪代码,仅展示主要功能:
public class LockFreeQueue<T>
{
private T[] array;
private int head;
private int tail;
public void Enqueue(T obj)
{
int tail = Interlocked.Increment(ref this.tail);
this.array[tail % this.array.Length] = obj;
}
public T Dequeue()
{
int head = Interlocked.Increment(ref this.head);
return this.array[head % this.array.Length];
}
}
通过 Interlocked 类的原子操作实现了无锁入队出队,这是一个典型的使用 CAS 实现无锁算法的例子。
CAS优缺点
优点:
- 无锁,实现高并发的数据结构。CAS 是实现无锁算法的关键手段。
- 原子操作,线程安全,不会引起数据竞争。
- 简单高效,只需要硬件支持,性能很高。
缺点:
- ABA 问题。如果一个值从
A改为B,又改回A,那么 CAS 操作会误认为值没有改变。常用的解决方法是使用版本号。 - 只能保证一个共享变量的原子操作。如果对多个共享变量操作,则需要使用锁。
- 资源浪费。当 CAS 失败时,会进行重试,消耗 CPU 资源。
- 只能在某些平台使用。需要硬件对 CAS 操作的支持,一些低端硬件并不支持 CAS。
综上,CAS 是实现无锁算法的关键手段,有很高的性能,但是也存在一定的问题,需要权衡使用。
一般适用场景:
- 当对一个共享变量的原子操作时,使用 CAS。
- 当操作多个共享变量时,使用锁可能性能更高。
- 如果硬件不支持 CAS,也不得不使用锁。
结论
CAS 是实现无锁算法的关键手段,性能高并发度高,但是也存在一定问题,需要权衡使用。一般来说,当操作一个共享变量时使用 CAS,操作多个共享变量时使用锁可能更高效。如果硬件不支持 CAS,也只能使用锁。
此外,CAS 和锁是两种不同的同步原语,各有优缺点,需要根据实际情况选择使用。CAS 是无锁算法的基石,所以高性能高并发系统中还是比较重要的
并发编程 --- CAS原子操作的更多相关文章
- 并发编程CAS操作
并发编程CAS操作 简介 CAS即compare and swap,中文就是比较并交换 CAS是Java并发包的基石 原理 其实CAS的原理相对来说比较简单.将要被改变的数据和期望的值作比较,当两个值 ...
- 并发编程--CAS自旋锁
在前两篇博客中我们介绍了并发编程--volatile应用与原理和并发编程--synchronized的实现原理(二),接下来我们介绍一下CAS自旋锁相关的知识. 一.自旋锁提出的背景 由于在多处理器系 ...
- JAVA并发编程: CAS和AQS
版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/u010862794/article/details/72892300 说起JAVA并发编程,就不得不聊 ...
- 从CAS讲起,真正高性能解决并发编程的原子操作
今天是猿灯塔“365天原创计划”第1天. 一.原子性操作 原子性操作:原子性在一个操作是不可中断的,要么全部执行成功要么全部执行失败,有着“同生共死”的感觉.及时在多个线程一起执行的时候,一个操作一旦 ...
- C++11并发编程:原子操作atomic
一:概述 项目中经常用遇到多线程操作共享数据问题,常用的处理方式是对共享数据进行加锁,如果多线程操作共享变量也同样采用这种方式. 为什么要对共享变量加锁或使用原子操作?如两个线程操作同一变量过程中,一 ...
- 并发编程之原子操作Atomic&Unsafe
原子操作:不能被分割(中断)的一个或一系列操作叫原子操作. 原子操作Atomic主要有12个类,4种类型的原子更新方式,原子更新基本类型,原子更新数组,原子更新字段,原子更新引用.Atomic包中的类 ...
- java并发编程之原子操作
先来看一段简单的代码,稍微有点并发知识的都可以知道打印出结果必然是一个小于20000的值 package com.example.test.cas; import java.io.IOExceptio ...
- Java并发编程-CAS
CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术.简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替 ...
- c++并发编程之原子操作的实现原理
原子(atomic)本意是”不能被进一步分割的最小粒子”,而原子操作(atomic operation)意为”不可被中断的一个或一系列操作”. 处理器如何实现原子操作 (1) 使用总线锁保证原子性 如 ...
- Java并发编程之原子操作类
什么是原子操作类当更新一个变量的时候,多出现数据争用的时候可能出现所意想不到的情况.这时的一般策略是使用synchronized解决,因为synchronized能够保证多个线程不会同时更新该变量.然 ...
随机推荐
- 获取Unity和UGUUI内置组件的属性名
需求来源 在阅读UGUI的源码时,发现Unity对于私有字段才加了[[SerializeField]]标签,而public的没有,且在Editor扩展中,也是查找带序列化标签的私有字段进行修改,那么在 ...
- 4.9 C++ Boost 命令行解析库
命令行解析库是一种用于简化处理命令行参数的工具,它可以帮助开发者更方便地解析命令行参数并提供适当的帮助信息.C++语言中,常用的命令行解析库有许多,通过本文的学习,读者可以了解不同的命令行解析库和它们 ...
- 群联预告满血PCIe 5.0 SSD主控:飙上14.7GB/s
群联电子将在CES 2024上展示两款新的PCIe 5.0 SSD主控方案,一个定位旗舰,一个面向主流. PCIe 5.0 SSD诞生已经差不多一年了,但是受限于群联E26主控的先天不足,以及闪存技术 ...
- 苹果正在测试新款Mac mini:搭载M3芯片 配备24GB大内存
据悉苹果目前正在测试新的Mac机型,亮点是采用最新的M3芯片. 据报道,首款搭载M3芯片的设备应该是13英寸的MacBook Pro和重新设计的MacBook Air,Mac mini机型并不在名单上 ...
- ESP8266的AT指令模块程序
最新代码可点击下载:ESP8266 模块代码 和以下代码实现方式不一致,更加自由可控 本段代码只是测试了esp8266作为服务器端使用,没有测试作为客户端使用. 没有超长延时等待或死循环等待AT指令反 ...
- 小知识:安装系统后唯独搜不到自己的Wi-Fi
遇到的问题,笔记本在安装Win10系统后在可用Wi-Fi热点中唯独搜不到自己的Wi-Fi. 咨询宽带售后的技术人员,说可能是因为我目前使用的是Wi-Fi 6,而我的笔记本可能是网卡过旧,不支持Wi-F ...
- 计网学习笔记九 Routing Fundamentals
在这一讲开始讲路由器的控制平面.简单介绍了routing,两个最小cost算法. 参考看的文章: VC网络中的路由 VC网络和数据报网络中路由的区别:Differences between Virtu ...
- NC16611 [NOIP2009]最优贸易
题目链接 题目 题目描述 C国有n个大城市和m条道路,每条道路连接这n个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这m条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向 ...
- NC16576 [NOIP2012]摆花
题目链接 题目 题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m 盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n 种花,从1 到n 标号.为了在门口展出更多种花,规定第i ...
- Python枚举类型enum
为什么需要枚举 枚举(Enum)是一种数据类型,也是一种特别的类,是绑定到唯一值的符号表示,可以使用它来创建用于变量和属性的常量集枚举类可以看成是一个下拉菜单,给出特定的选项且这些选项不可修改,更贴近 ...