【Java并发编程实战】-----“J.U.C”:CAS操作
CAS,即Compare and Swap,中文翻译为“比较并交换”。
对于JUC包中,CAS理论是实现整个java并发包的基石。从整体来看,concurrent包的实现示意图如下:

i++是一个非常经典的操作,它几乎充斥着我们每个人编写的代码中。我们知道i++是可以分解的,它分解为getI()、i + 1 、setI三个步骤,所以它并不是原子操作。如果i==1,执行两次i++操作,我们期望的结果是3,但是结果有可能也是2:

那么有什么办法解决这个问题呢?肯定有!使用锁即可:
synchronized(this){
i++;
}
诚然,在java中存在乐观锁、悲观锁两种锁。其中synchronized就是悲观锁,在前面我们了解synchronized也是独占锁,加入关键字synchronized的代码一般都是以单线程的形式在运行着,它会导致其他需要该资源的线程挂起直到前面的线程执行完毕释放资源,所以它的效率较为低下。而乐观锁则采用了一种较为高效的方式,它的操作与synchronized不同,synchronized采用加锁,而它则不采用加锁去执行某些操作,如果发生了冲突则失败并一直重试直到成功为止。而CAS就是一种乐观锁,它所采用的策略是当且仅当预期值A和存中的值V相同,则将内存V值修改为B,否则返回V。实现如下:
for(;;){
if(A==V){
V = B;
}
}
当然在J.U.C中实现CAS没有这么简单。
CAS
CAS,即一种对内存中的共享数据进行操作的指令,而且该操作是原子的读写操作。其过程如下:首先CPU将内存中的将要被修改的数据与预期的值进行比较,如果这两个值相等,CPU则会将内存中数值替换为新值,否则不做操作。最后,CPU会将旧值返回。在java中,CAS的含义就是“我认为的原本的值是什么,如果你是,则更换为新值,否则不做修改同时麻烦告诉我该值时多少”。
在CAS中,总共存在三个操作数:预期值A、内存中的V、修改的值B。当且仅当预期值A和内存中的值V相同,则将内存V值修改为B,否则返回V。使用这种机制编写的算法也叫作非阻塞算法,标准定义了一个线程的失败或者挂起是不会影响其他线程的失败或者挂起。
下面我们来已AtomicIneger的源码为例来看看CAS操作:
public final int getAndAdd(int delta) {
for (;;) {
int current = get();
int next = current + delta;
if (compareAndSet(current, next))
return current;
}
}
这里很显然使用CAS操作(for(;;)里面),他每次都从内存中读取数据,+1操作,然后两个值进行CAS操作。如果成功则返回,否则失败重试,直到修改成功为止。
上面源码最关键的地方有两个,一个for循环,它代表着一种宁死不屈的精神,不成功誓不罢休。还有就是compareAndSet:
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
CAS的缺陷
尽管CAS机制可以使我们不依赖与同步,不影响和挂起其他线程,它大大提升了运行的效率,但是它会导致一个ABA的问题,如下:加入有两个线程A、B,他们都读取内存中的数据V,假如这个时候线程A,先将V修改为V1,然后又修改为V,这个时候线程B的compareAndSet仍然能成功,对于线程B而言该值V并没有发生任何变化,而实际上它已经变化了,只不过最后又还原了而已。
参考文献
【Java并发编程实战】-----“J.U.C”:CAS操作的更多相关文章
- 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock
ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...
- 【Java并发编程实战】-----“J.U.C”:CountDownlatch
上篇博文([Java并发编程实战]-----"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一 ...
- 【Java并发编程实战】-----“J.U.C”:CyclicBarrier
在上篇博客([Java并发编程实战]-----"J.U.C":Semaphore)中,LZ介绍了Semaphore,下面LZ介绍CyclicBarrier.在JDK API中是这么 ...
- 【Java并发编程实战】-----“J.U.C”:Semaphore
信号量Semaphore是一个控制访问多个共享资源的计数器,它本质上是一个"共享锁". Java并发提供了两种加锁模式:共享锁和独占锁.前面LZ介绍的ReentrantLock就是 ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之三unlock方法分析
前篇博客LZ已经分析了ReentrantLock的lock()实现过程,我们了解到lock实现机制有公平锁和非公平锁,两者的主要区别在于公平锁要按照CLH队列等待获取锁,而非公平锁无视CLH队列直接获 ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之一简介
注:由于要介绍ReentrantLock的东西太多了,免得各位客官看累,所以分三篇博客来阐述.本篇博客介绍ReentrantLock基本内容,后两篇博客从源码级别分别阐述ReentrantLock的l ...
- 【Java并发编程实战】----- AQS(四):CLH同步队列
在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形.其主要从两方面进行了改造:节点的结构与节点等待机制.在结构上引入了头 ...
- 【Java并发编程实战】—– AQS(四):CLH同步队列
在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形. 其主要从双方面进行了改造:节点的结构与节点等待机制.在结构上引入了 ...
- 【Java并发编程实战】----- AQS(二):获取锁、释放锁
上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...
- 《java并发编程实战》笔记
<java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为: Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...
随机推荐
- 开源:ASP.NET Aries 开发框架
前言: 随着岁月的推进,不知不觉已在.NET这领域上战斗了十年了. 青春还没来得急好好感受,却已是步入健忘之秋的老人一枚了. 趁着还有点记忆,得赶紧把硬盘里那私藏的80G除外的东西,和大伙分享分享. ...
- [C#] 软硬结合第二篇——酷我音乐盒的逆天玩法
1.灵感来源: LZ是纯宅男,一天从早上8:00起一直要呆在电脑旁到晚上12:00左右吧~平时也没人来闲聊几句,刷空间暑假也没啥动态,听音乐吧...~有些确实不好听,于是就不得不打断手头的工作去点击下 ...
- webpack入门教程之Hello webpack(一)
webpack入门教程系列为官网Tutorials的个人译文,旨在给予想要学习webpack的小伙伴一个另外的途径.如有不当之处,请大家指出. 看完入门教程系列后,你将会学习到如下内容: 1.如何安装 ...
- 在 Laravel 中使用图片处理库 Integration/Image
系统需求 PHP >= 5.3 Fileinfo Extension GD Library (>=2.0) … or … Imagick PHP extension (>=6.5.7 ...
- 【原】AFNetworking源码阅读(三)
[原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...
- javascript之Object.defineProperty的奥妙
直切主题 今天遇到一个这样的功能: 写一个函数,该函数传递两个参数,第一个参数为返回对象的总数据量,第二个参数为初始化对象的数据.如: var o = obj (4, {name: 'xu', age ...
- [.NET] 怎样使用 async & await 一步步将同步代码转换为异步编程
怎样使用 async & await 一步步将同步代码转换为异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6079707.html ...
- 几个有趣的WEB设备API 前端提高B格必备(一)——电池状态&震动api
受到同事启发,突然发现了几个有趣又实用的web api,没想到前端还有这么多有趣的东西可以玩~~简直过分. 1.电池状态API navigator.getBattery():这个api返回的是一个pr ...
- ASP.NET Core 中文文档 第五章 测试(5.2)集成测试
原文: Integration Testing 作者: Steve Smith 翻译: 王健 校对: 孟帅洋(书缘) 集成测试确保应用程序的组件组装在一起时正常工作. ASP.NET Core支持使用 ...
- TYPESDK手游聚合SDK服务端设计思路与架构之二:服务端设计
在前一篇文中,我们对一个聚合SDK服务端所需要实现的功能作了简单的分析.通过两个主要场景的功能流程图,我们可以看到,作为多款游戏要适配多个渠道的统一请求转发中心,TYPESDK服务端主要需要实现的功能 ...