并发编程(五):CAS
在atomic包中,大多数类都是借助unsafe类来实现的,如以下代码
public static AtomicInteger count = new AtomicInteger(0); private static void add() {
count.incrementAndGet();
}
incrementAndGet()方法的实现如下:
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
我们再继续深入getAndInt()方法,实现如下:
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5;
}
在以上代码中我们着重要说的是 compareAndSwapInt(var1, var2, var5, var5 + var4) 这个方法,compareAndSwap,取每个单词首写字母,就是我们经常说的cas。这个方法中有四个参数var1为当前对象,即代码中的count,var2为当前值,如想计算2加上1等于3的操作,var2即为2,var4为增加量,也就是这个例子中的1,var5为调用底层方法得到的底层当前的值,如果没有其他线程改变底层当前值,返回为2,compareAndSwapInt方法的作用为,如果var2(当前值)与var5(底层当前值相等)则将底层值覆盖为底层当前值(var5)+增加量(var4),否则(其他线程更改了底层当前值,var5不等于var2),重新从底层方法取一次var5的值,如此时var5=4,并重新从var1(当前对象)取一次var2的值,如此时var2的值也变为4,则采取相加操作覆盖底层值,如果var2与var5仍不等,则继续循环取值,直到相等为止。
总结一下,CAS操作包含三个操作数,内存位置(V),预期原值(A)和新值(B),如果内存位置的值与预期原值相匹配,处理器会自动将该位置值更新为新值,否则处理器不做任何操作。CAS指令一般都返回该位置的值(有特殊情况只返回是否成功),CAS简而言之就是,我认为位置V应该包含值A,如果包含该值,就将B放到这个位置,否则不更改该位置的值,只告诉我这个位置现在的值即可 。
对于getIntVolatile方法和compareAndSwapInt的实现如下:
public native int getIntVolatile(Object var1, long var2);
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
可将两个方法都由native修饰,native修饰的方法为底层方法,一般由c语言来实现。
锁分为悲观锁和乐观锁,独占锁是一种悲观锁,synchronized是一种独占锁,如果锁被占用,其他需要锁的线程就会被挂起,直到持有锁的线程释放锁,它会产生的问题如下:
a、在多线程竞争下,加锁释放锁会导致比较多的上下文切换和调度延时,引起性能问题
b、如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险
另一种就是乐观锁,它每次执行时并不加锁而是假设没有冲突的去完成操作,如果因为冲突失败就重试,直到成功为止,而客观锁用到的机制就是CAS。虽然CAS可以很高效的解决原子操作,但是CAS仍然存在三大问题:
a、ABA问题,如果一个值原来是A,后被改成B,之后又改为A,那么使用CAS进行检查时发现它的值并没有发生变化,但是实际上却发生变化了,ABA问题的解决思路就是使用版本号,在变量面前加上版本号,每次变量更新的时候把版本加一,上面博客中我们提到atomic包中有专门的类来解决ABA问题
b、循环时间长开销大。CAS循环如果长时间不成功,会给CPU带来非常大的执行开销。如果JVM能支持处理器提供的pause指令则效率会有一定的提升,pause指令有两个作用,推迟流水线执行,使cpu不会消耗过多的执行资源和避免退出循环的时候因内存顺序冲突而引起CPU流水线被清空,提高CPU执行效率
c、只能保证一个共享变量的原子操作。当对一个共享变量执行操作时,我们可以使用循环CAS来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候可以用锁或把多个共享变量合并成一个共享变量来操作或者把多个变量放在一个对象里(atomic包中有对引用类型的原子操作)来进行CAS操作
并发编程(五):CAS的更多相关文章
- 【Java并发编程五】信号量
一.概述 技术信号量用来控制能够同时访问某特定资源的活动的数量,或者同时执行某一给定操作的数据.计数信号量可以用来实现资源池或者给一个容器限定边界. 信号量维护了一个许可集,许可的初始量通过构造函数传 ...
- java并发编程(八) CAS & Unsafe & atomic
参考文档:https://www.cnblogs.com/xrq730/p/4976007.html CAS(Compare and Swap) 一个CAS方法包含三个参数CAS(V,E,N).V表示 ...
- Java并发编程 (五) 线程安全性
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.安全发布对象-发布与逸出 1.发布与逸出定义 发布对象 : 使一个对象能够被当前范围之外的代码所使用 ...
- 聊聊CAS - 面试官最喜欢问的并发编程专题
什么是CAS 学习Java并发编程,CAS(Compare And Set)机制都是一个不得不掌握的知识点.除了通过synchronized进行并发控制外,还可以通过CAS的方式控制,大家熟悉的Ree ...
- Java并发(一)并发编程的挑战
目录 一.上下文切换 1. 多线程一定快吗 2. 测试上下文切换次数和时长 3. 如何减少上下文切换 4. 减少上下文切换实战 二.死锁 三.资源限制的挑战 四.本章小结 并发编程的目的是为了让程序运 ...
- java(9)并发编程
整理自<java 并发编程的艺术> 1. 上下文切换 即使是单核处理器也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现这个机制.时间片是CPU分配给各个线程的时间,因为时间 ...
- 读《Java并发编程的艺术》(一)
离开博客园很久了,自从找到工作,到现在基本没有再写过博客了.在大学培养起来的写博客的习惯在慢慢的消失殆尽,感觉汗颜.所以现在要开始重新培养起这个习惯,定期写博客不仅是对自己学习知识的一种沉淀,更是在督 ...
- java并发编程的艺术——第一章总结
并发编程的挑战 1.1上下文切换 1.2死锁 1.3资源限制的挑战 1.4本章小结 1.1上下文切换 1.1.1多线程一定快吗 1.1.2测试上下文切换次数和时长 1.1.3如何减少上下文切换 1.1 ...
- 《Jave并发编程的艺术》学习笔记(1-2章)
Jave并发的艺术 并发编程的挑战 上下文切换 CPU通过时间片分配算法来循环执行任务,当前时间片执行完之后会切换到下一个任务.但是,切换会保存上一个任务的状态,一遍下次切换回这个任务时,可以再次加载 ...
- Java并发编程的挑战
并发编程的目的是为了让程序运行得更快,但是,并不是线程启动的越多,就能让程序最大限度地并发执行.并发编程时,会面临非常多的挑战,比如上下文切换的问题,死锁的问题,以及受限于各种硬件和软件的资源限制问题 ...
随机推荐
- 学习笔记3-开发与运行(卸载)第一个ANDROID应用
新建Android项目 1. 配置好Android坏境以后,新建项目选择Android Project. 2. 选择针对哪个平台开发的应用(Android2/Android4等) ...
- (七十三)iOS本地推送通知的实现
iOS的推送通知分为本地推送和网络推送两种,如果App处于挂起状态,是可以发送本地通知的,如果已经被杀掉,则只有定时通知可以被执行,而类似于QQ的那种网络消息推送就无法实现了,因为App的网络模块在被 ...
- React Native移植原生Android
(一)前言 之前已经写过了有关React Native移植原生Android项目的文章,不过因为RN版本更新的原因吧,跟着以前的文章可能会出现一些问题,对于初学者来讲还是会有很多疑难的困惑的,而且官方 ...
- Mybatis源码之Statement处理器StatementHandler(一)
StatementHandler通过类名我们可以了解到它可能是Statement的处理器,它是一个接口,其实现类如下: BaseStatementHandler:一个抽象类,只是实现了一些不涉及具体操 ...
- UNIX环境高级编程——进程间通讯方法整理
一.无名管道pipe #include <unistd.h> int pipe(int fd [2]) 二.fifo #include <sys/stat.h> int mkf ...
- 如何利用BI搭建电商数据分析平台
某电商是某大型服装集团下的重要销售平台.2015 年,该集团品牌价值达数百亿元,产品质量.市场占有率.出口创汇.销售收入连年居全国绒纺行业第一,在中国有终端店3000多家,零售额80 亿.其羊绒制品年 ...
- 【翻译】使用Sencha Ext JS 6打造通用应用程序
原文:Using Sencha Ext JS 6 to Build Universal Apps {.aligncenter} 在Sencha和整个Ext JS团队的支持下,我很高兴能跟大家分享一下有 ...
- hive的top n
注意 hive 的hsql没有 top n这个功能,不像sql. 所以实现top n如下: 我想说的SELECT TOP N是取最大前N条或者最小前N条. Hive提供了limit关键字,再配合ord ...
- Linux 句柄是什么 ?
1.句柄就是一个标识符,只要获得对象的句柄,我们就可以对对象进行任意的操作. 2.句柄不是指针,操作系统用句柄可以找到一块内存,这个句柄可能是标识符,map的key,也可能是指针,看操作系统怎么处理的 ...
- 海量数据挖掘MMDS week4: 推荐系统之数据降维Dimensionality Reduction
http://blog.csdn.net/pipisorry/article/details/49231919 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...