原子操作:CAS、TAS、TTAS、FAA浅析
原子操作:CAS、TAS、TTAS、FAA浅析
什么是原子操作
原子操作(atomic operation)是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。保证访问共享资源是唯一的。
一般原子操作需要CPU等硬件支持,使用硬件同步原语来实现原子操作。常用的原语有CAS(compare-and-swap)
、TES(test-and-set)
、FAA(fetch-and-add)
CAS
什么是CAS
在计算机科学中,比较与交换(CAS)是多线程中用来实现同步的原子指令。它将内存位置的内容与给定值进行比较,只有当它们相同时,才将该内存位置的内容修改为新的给定值。这是作为单个原子操作完成的
// wiki的伪代码
function cas(p : pointer to int, old : int, new : int) returns bool {if *p ≠ old {return false}*p ← newreturn true
}
当内存值发生变化后,一直使用cas原语去尝试更新值时,叫做自旋。
cas的存在的问题
ABA problem
wiki ABA问题
ABA问题可以简单的转换为,线程或者进程两次读取相同的值以后是否关注在两次读取之前变量的值是否发送改变,如果中间的改变会影响计算结果,就会出现ABA问题,如果只关注值本身,那么即使出现了ABA也不会影响程序执行结果。
如:
A 读取到 V的值 100 挂起(线程切换)
B 读取到V的值 100 继续执行,比较并交换后更新为40,退出
C 读取到V的值为40,比较并更新为100,退出
A 继续执行,因为V的值为100,A可以对V进行操作可以把V的值设置为70
以上例子可以看出发生了ABA的问题,但是对于以上案例来说,对程序执行结果并没有影响。
如:
S是一个链表 a->b->a->e
A 要获取到a结点想把a替换为f,预期结果为f->b->a->e->e,但是A被挂起了(线程切换)
B 要获取a以后删掉a结点,B执行成功 变为b->a->e
C获取到b结点以后删除来了b C执行成功 变为a->e
A 被唤醒继续执行 发现链表的头还是a,执行结果为 f->e 【实际不应该在继续更新的,因为此a非彼a】
以上例子可以看出来发生了ABA问题,ABA问题也导致了程序执行异常。因为无法保证现在的a还是之前的a,那么怎么保证现在的a是之前的a?通用的做法就是给打个标记(版本号)。那么怎么打标记呢?
前人也提供了很多解决方案:
1. 使用double-length CAS (DCAS)
.在32位系统上,可以使用64位CAS,64位的内存可以分为两个部分。一部分用于存放具体的值,一部分用于存放版本信息,这样就可以解决ABA的问题,当然在64的情况下,可以使用128位CAS。
2. 对于不支持DCAS
的CPU,如果是32位系统,可以认为进行拆分,如,前16位用于版本信息,后16位用于对应的值。
3. 使用一个更复杂但更有效的解决方案是实施安全内存回收(SMR)(了解即可)
Costs and benefits
多线程反复尝试更新某一个变量,太多重试自旋,会消耗大量CPU资源,会给CPU带来很大的压力。
因此冲突如果过于频繁的场景不建议使用CAS原语进行处理(CAS也是乐观锁的机制,乐观锁不擅长冲突频繁的场景,这时候可以选择悲观锁的机制)
TAS
什么是TAS
在计算机科学中,test-and-set指令是一种用来将1 (set)写入一个内存位置,并以单个原子的形式返回其旧值的指令。,不可中断)操作。
// wiki 伪代码
function Lock(boolean *lock) { while (test_and_set(lock) == 1);
}
TAS特点是自旋,也就是循环,每次尝试去设置值,如果设置成功则会返回,如果没有返回就会一直自旋,知道设置成功值。此时进入临界区,执行完临界区数据,再设置bool变量为false。从而让其他线程拿到锁。
volatile int lock = 0;void Critical() {while (TestAndSet(&lock) == 1);critical section // only one process can be in this section at a timelock = 0 // release lock when finished with the critical section}
TAS的问题
当使用TAS实现TASLock (Test And Set Lock)测试-设置锁,它的特点是自旋时,每次尝试获取锁时,底层还是使用CAS操作,不断的设置锁标志位的过程会一直修改共享变量的值(回写),会引发缓冲一致性流量发风暴。【因为每一次CAS操作都会发出广播通知其他处理器
,从而影响程序的性能。】
为什么回写会影响性能?
【因为每一次CAS操作都会发出广播通知其他处理器
,通知的过程会出现总线锁定,从而影响程序的性能。】
TTAS
什么是TTAS
Test and test-and-set 用于在多处理器环境中实现互斥的指令。为了解决TAS过程中通过CAS不断修改共享变量而导致的性能问题,而提出的方案。
TTAS的特点也是自旋,主要是为了降低性能开销,主要思路是减少回写(CAS
导致的不断修改共享变量的值)。第一步先去检测 lock
是否空闲;不可用就让出CPU,可用就执行TAS
进行CAS
操作,只有一个线程先观测到lock
是空闲的,该线程才会尝试的去获取它,从而消除一部分回写操作。
// wiki
boolean locked := false // shared lock variable
procedure EnterCritical() {do {while (locked == true) yield(); // lock looks busy so yield to scheduler} while TestAndSet(locked) // actual atomic locking
}
procedure TestAndSet(lock) {boolean initial = lock;lock = true;return initial;}
FAA
什么是FFA
Fetch-and-add指令将存储位置的内容增加指定的值(原子操作)。其他线程无法观测中间结果。
FAA特点就是原子性,因为在多处理器的计算中进行x=x+a的操作,实际上有三步:
- 获取变量x的地址,把x的值放到寄存器中
- 在寄存器增加a
- 把寄存器的新值放到x的地址中。
FAA的意义就是把这三步原子化,要么都执行要么都不执行。
// wiki
function FetchAndAdd(address location, int inc) {int value := *location*location := value + increturn value
}
FFA的存在的问题
FFA的使用场景比较局限(自增自建的场景如计数器。
参考资料
原子操作百度百科
聊聊高并发(六)实现几种自旋锁(一)
原子操作:CAS、TAS、TTAS、FAA浅析相关推荐
- java原子操作cas_java并发编程系列二:原子操作/CAS
什么是原子操作 不可被中断的一个或者一系列操作 实现原子操作的方式 Java可以通过锁和循环CAS的方式实现原子操作 CAS( Compare And Swap ) 为什么要有CAS? Compar ...
- 从“惊群”的现象来看并发锁,“死锁”问题的解决方案丨Redis单线程|共享内存|无锁实现|原子操作CAS
从"惊群"的现象来看并发锁,"死锁"问题的解决方案 视频讲解如下,点击观看: 从"惊群"的现象来看并发锁,"死锁"问题的 ...
- 原子操作CAS,原子性操作类
原子操作CAS CAS的原理 CAS(Compare And Swap),指令级别保证这是一个原子操作 三个运算符: 一个内存地址V,一个期望的值A,一个新值B 基本思路:如果地址V上的值和期望的值 ...
- CAS、原子操作类的应用与浅析及Java8对其的优化
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:CoderBear juejin.im/post/5c7a8 ...
- Java并发编程(十一)——原子操作CAS
一.原子操作 syn基于阻塞的锁的机制,1.被阻塞的线程优先级很高,2.拿到锁的线程一直不释放锁怎么办?3.大量的竞争,消耗cpu,同时带来死锁或者其他安全. CAS的原理 CAS(Compare A ...
- 并发编程(三)原子操作CAS
1.CAS(Compare And Swap)原子操作: 假定有两个操作A和B,如果从执行A的线程来看,当另一个线程执行B时,要么将B全部执行完,要么完全不执行B,那么A和B对彼此来说是原子的. 通过 ...
- java多线程原子操作_Java 多线程 - 原子操作CAS
什么是原子操作?如何实现原子操作? 假定有两个操作 A 和 B,如果从执行 A 的线程来看,当另一个线程执行 B 时, 要么将 B 全部执行完,要么完全不执行 B,那么 A 和 B 对彼此来说是原子的 ...
- java 什么是原子操作_java原子操作CAS
本次内容主要讲原子操作的概念.原子操作的实现方式.CAS的使用.原理.3大问题及其解决方案,最后还讲到了JDK中经常使用到的原子操作类. 1.什么是原子操作? 所谓原子操作是指不会被线程调度机制打断的 ...
- Java线程CAS原子操作
这次分享一些关于原子操作(CAS)的东西. 定义 CAS(Compare And Swap)是CPU的一个指令级别的操作,叫原子操作,原子操作是不可分割的,跟事务差不多,要么全部执行完成,要么不执行: ...
- Java原子操作类,你知道多少?
原子操作类简介 由于synchronized是采用的是悲观锁策略,并不是特别高效的一种解决方案. 实际上,在J.U.C下的atomic包提供了一系列的操作简单,性能高效,并能保证线程安全的类去 更新基 ...
最新文章
- linux oraclerman自动备份,Linux平台下的Oracle自动备份案例(使用RMAN)
- 智源青年科学家候选人 | 张祥雨:挑战自动化深度学习系统
- 时频特性分析(Matlab)
- python 最小栈
- 业界 | 5个步骤开启你的数据科学职业生涯!(附链接)
- 数据库 文件 备份【学习 使用】
- 后端model传入前端JSP页面中的值判断后再取值
- 用matlab抽样定理验证,MATLAB抽样定理验证.docx
- linux命令 socket,如何从linux中的命令行向socket.io websocket发送消息?
- 华为nova 8 Pro王者荣耀定制版曝光:内置小鲁班定制主题 电池盖镭雕小鲁班
- LitePal的升级
- html前端登录界面示例
- xmlspy2014下载安装(可用)
- 1、u3d 下载、安装
- android投影到创维电视,创维电视怎么投屏?图文讲解安卓和苹果手机投屏到创维电视方法...
- 【吐槽】B站大量番剧下架,程序猿们这时都在干什么?
- allegro使用汇总
- 我的世界java播放背景音乐_我的世界BOSS音乐mod
- 计算机日常故障DIY维修有哪些,计算机维护 DIY 完全手册
- 基于STM32F407+RFID的模拟公交车刷卡收费系统小项目
热门文章
- SCI收录中国期刊一览表
- python怎么输入矩阵命令_python矩阵操作
- GSM、UMTS和LTE网络;FDD,TDD双工模式
- 时钟的同步与异步问题
- linux时钟(时间)同步
- 调用百度地图API进行当前位置定位失败解决方法
- FLUKE OTDR光纤测试仪OFP2-100-Q双光纤双向测试的方法
- 解决UmengSDK社会化分享过程中微信,QQ,新浪微博分享不成功的问题
- 华为系统升级提示服务器不可用怎么办,更新服务器不可用
- 基于AD9979+夏普sharp 1/3英寸130万像素CCD成像组件设计