比较并交换(compare and swap, CAS)
比较并交换(compare and swap, CAS),是原子操作的一种,可用于在多线程编程中实现不被打断的数据交换操作,从而避免多线程同时改写某一数据时由于执行顺序不确定性以及中断的不可预知性产生的数据不一致问题。 该操作通过将内存中的值与指定数据进行比较,当数值一样时将内存中的数据替换为新的值。
概述[编辑]
一个CAS操作的过程可以用以下c代码表示: [1]
1 int cas(long *addr, long old, long new)
2 {
3 /* Executes atomically. */
4 if(*addr != old)
5 return 0;
6 *addr = new;
7 return 1;
8 }
在使用上,通常会记录下某块内存中的旧值,通过对旧值进行一系列的操作后得到新值,然后通过CAS操作将新值与旧值进行交换。如果这块内存的值在这期间内没被修改过,则旧值会与内存中的数据相同,这时CAS操作将会成功执行 使内存中的数据变为新值。如果内存中的值在这期间内被修改过,则一般[2]来说旧值会与内存中的数据不同,这时CAS操作将会失败,新值将不会被写入内存。
应用[编辑]
在应用中CAS可以用于实现无锁数据结构,常见的有无锁队列(先入先出)[3] 以及无锁堆(先入后出)。对于可在任意位置插入数据的链表以及双向链表,实现无锁操作的难度较大。[4]。
ABA问题[编辑]
ABA问题是无锁结构实现中常见的一种问题,可基本表述为:
- 进程P1读取了一个数值A
- P1被挂起(时间片耗尽、中断等),进程P2开始执行
- P2修改数值A为数值B,然后又修改回A
- P1被唤醒,比较后发现数值A没有变化,程序继续执行。
对于P1来说,数值A未发生过改变,但实际上A已经被变化过了,继续使用可能会出现问题。在CAS操作中,由于比较的多是指针,这个问题将会变得更加严重。试想如下情况:
top
|
V
0x0014
| Node A | --> | Node X | --> ……
有一个堆(先入后出)中有top和节点A,节点A目前位于堆顶top指针指向A。现在有一个进程P1想要pop一个节点,因此按照如下无锁操作进行
pop()
{
do{
ptr = top; // ptr = top = NodeA
next_prt = top->next; // next_ptr = NodeX
} while(CAS(top, ptr, next_ptr) != true);
return ptr;
}
而进程P2在执行CAS操作之前打断了P1,并对堆进行了一系列的pop和push操作,使堆变为如下结构:
top
|
V
0x0014
| Node C | --> | Node B | --> | Node X | --> ……
进程P2首先pop出NodeA,之后又Push了两个NodeB和C,由于内存管理机制中广泛使用的内存重用机制,导致NodeC的地址与之前的NodeA一致。
这时P1又开始继续运行,在执行CAS操作时,由于top依旧指向的是NodeA的地址(实际上已经变为NodeC),因此将top的值修改为了NodeX,这时堆结构如下:
top
|
0x0014 V
| Node C | --> | Node B | --> | Node X | --> ……
经过CAS操作后,top指针错误的指向了NodeX而不是NodeB。
实现[编辑]
CAS操作基于CPU提供的原子操作指令实现。对于Intel X86处理器,可通过在汇编指令前增加LOCK前缀来锁定系统总线,使系统总线在汇编指令执行时无法访问相应的内存地址。而各个编译器根据这个特点实现了各自的原子操作函数。[5]
- C语言,C11的头文件<stdatomic.h>。由GNU提供了对应的__sync系列函数完成原子操作。 [6][7]
- C++11,STL提供了atomic系列函数。[8][7]
- JAVA,sun.misc.Unsafe提供了compareAndSwap系列函数。[9]
- C#,通过Interlocked方法实现。[10]
- Go, 通过import "sync/atomic"包实现。[11]
- Windows,通过Windows API实现了InterlockedCompareExchangeXYZ系列函数。[12][7]
比较并交换(compare and swap, CAS)的更多相关文章
- Compare and Swap [CAS] 算法
一个Java 5中最好的补充是对原子操作的支持类,如AtomicInteger,AtomicLong等.这些类帮助你减少复杂的(不必要的)多线程代码,实际上只是完成一些基本操作,如增加或减少多个线程之 ...
- Compare and Swap(CAS)
CAS(Compare and Swap)是个原子操作.拿到一个新值后,CAS将其与内存中的值进行比较,若内存中的值和这个值不一样,则将这个值写入内存,否则,不做操作.在Java的 java.util ...
- 非阻塞同步算法与CAS(Compare and Swap)无锁算法
锁(lock)的代价 锁是用来做并发最简单的方式,当然其代价也是最高的.内核态的锁的时候需要操作系统进行一次上下文切换,加锁.释放锁会导致比较多的上下文切换和调度延时,等待锁的线程会被挂起直至锁释放. ...
- 【Java并发编程】9、非阻塞同步算法与CAS(Compare and Swap)无锁算法
转自:http://www.cnblogs.com/Mainz/p/3546347.html?utm_source=tuicool&utm_medium=referral 锁(lock)的代价 ...
- Java并发基础之Compare And Swap/Set(CAS)
什么是 CAS?CAS(Compare And Swap/Set)比较并交换, CAS 算法的过程是这样:它包含 3 个参数CAS(V,E,N). V 表示待更新的变量(内存值), E 表示预期值(旧 ...
- CAS(Compare and Swap)理解
什么叫CAS(Compare and Swap)? 硬件同步原语!! 什么蛋疼的名字,一般人很难理解.根据英文全称翻译==比较与交换,这个名字大致还能理解一点,目前先暂且这么理解吧. 有啥用处? 对 ...
- Java多线程和并发(十一),CAS(Compare and Swap)
目录 1.CAS简介 2.CAS多数情况下对开发者来说是透明的 3.CAS缺点 十一.CAS(Compare and Swap) Synchronized直观意义上是一种悲观锁 cas则是乐观锁的一种 ...
- 无锁机制----比较交换CAS Compare And Swap
一.锁与共享变量 加锁是一种悲观的策略,它总是认为每次访问共享资源的时候,总会发生冲突,所以宁愿牺牲性能(时间)来保证数据安全. 无锁是一种乐观的策略,它假设线程访问共享资源不会发生冲突,所以不需要加 ...
- 面试:为了进阿里,又把并发CAS(Compare and Swap)实现重新精读一遍
该系列文章已收录在公众号[Ccww技术博客],原创技术文章第一时间推出 前言 在面试中,并发线程安全提问必然是不会缺少的,那基础的CAS原理也必须了解,这样在面试中才能加分,那来看看面试可能会问那些问 ...
- CAS(Compare and Swap)无锁算法-学习笔记
非阻塞同步算法与CAS(Compare and Swap)无锁算法 这篇问题对java的CAS讲的非常透彻! 锁的代价 1. 内核态的锁的时候需要操作系统进行一次上下文切换,加锁.释放锁会导致比较多的 ...
随机推荐
- nf_conntrack: table full, dropping packet
参考:linux 路由跟踪表满错误 nf_conntrack: table full, dropping packet 原理解决方法 说明 ping,dmesg 或者 /var/log/message ...
- Linux 命令:rpm查询选项
rpm(8) System Manager's Manual rpm(8) 名称 rpm - RPM 软件包管理器 查询选项 rpm的查询命令通常的格式如下: rpm -q [query-option ...
- linux 字符集与编码格式相关
字符集:多个字符的集合. # 书写系统字母与符号的集合. 字符编码:把 字符集 中的字符 编码为(映射)指定集合中的某一对象. # 以便文本在计算机中存储和通过通信网络的传递 查看文件的的编码格式 ...
- Linux 下的 OpenGL 之路(九):天空盒、反射和折射
前言 搞定了天空盒,才算是真正完成了场景的搭建,以后再要进行什么样的图形学测试,都可以在这个场景下进行.比如后面的反射.折射就是这样的例子. 写完这篇,我决定暂时结束这个系列.主要是因为我太懒了,居然 ...
- Pandas:在DataFrame中添加一行,并设置行索引
解决方案 效果图 参考链接 https://blog.csdn.net/Caiqiudan/article/details/107788525
- croc-文件传输工具
前言 croc是一款用go语言开发的命令行文件传输工具,该工具允许两台计算机设备以一种简单和安全的方式来传输文件. GitHub项目地址 环境信息 IP 系统版本 croc版本 说明 192.168. ...
- 详细讲解原生js拖拽
场景描述 今天遇见一个问题,那就是产品希望在弹出来的窗口. 可以移动这个弹窗的位置 增加用户体验,我们直接使用的element-ui中的 Dialog 对话框 我们现在需要拖拽标题,移动元素位置 元素 ...
- C#程序变量统一管理例子 - 开源研究系列文章
今天讲讲关于C#应用程序中使用到的变量的统一管理的代码例子. 我们知道,在C#里使用变量,除了private私有变量外,程序中使用到的公共变量就需要进行统一的存放和管理.这里笔者使用到的公共变量管理库 ...
- cs50ai1
cs50ai1-------Knowledge cs50ai1-------Knowledge 基础知识 课后题目 代码实践 学习链接 总结 基础知识 对我们来说,一些基本的logic是自然而然的,我 ...
- 《SQL与数据库基础》21. 分库分表(一)
目录 分库分表(一) 拆分策略 垂直拆分 垂直分库 垂直分表 水平拆分 水平分库 水平分表 技术实现 MyCat概述 概念介绍 环境准备 目录介绍 MyCat入门 配置 分片配置(schema.xml ...