3.CAS原子操作
什么是原子性操作,按照官方的解析:原子操作不能在一个中间操作中停止,要么全部成功要么全部失败。(An atomic action cannot stop in the middle: it either happens completely, or it doesn't happen at all. No side effects of an atomic action are visible until the action is complete.),
-- 除了long和double的读写,其他的引用变量的读写操作都是原子性的
-- 如果加了volatile关键字,所有的引用变量的读写操作都是原子性的。
-- 原子操作不会被其他的线程干扰。但是会存在内存不一致(consistency memory)的问题。但是使用关键字volatile可以大大减少这个风险。
-- 线程修改volatile变量的时候,会在这个变量上面和其他的读取该变量的读线程上面建立一个happens-before的关系。保证写线程对该变量的修改对其他的读线程是可见的。
compare and swap.在一个内存地址V,一个期望值A,一个新值B。如果在V上面是期望的A值,那么用B值去替换。否则通过自旋方式(死循环)一直到找到期望值位置。
3.1 为什么要有CAS,传统的锁有什么弊端
传统的锁实现比较笨重,如果程序中需要对某些计算变量实现原子性,是用java的锁会很笨重。而且给资源加锁如果控制不得当的话,容易出现死锁的现象。而CAS的出现就是为了解决在无锁的情况下也可以实现对于
资源的原子操作。
3.2 CAS的问题
+ CAS容易产生ABA问题,就是一个内存地址V,值是A。有一个a线程要去修改它的值,此时有一个b线程把A的值改为了B,然后再改回A,此时对于a线程来说,它对于b线程的修改操作时无感知的。为了解决ABA问题,引入了版本号。所有
线程修改一个内存的值前要先获取值的版本号,修改完后需要更新版本号。这似乎就需要使用AtomicStampedReference来操作了。如果是不关心值是否被修改过的情况,不需要考虑ABA问题。
+ 因为CAS会以自旋的方式索引期望值,如果一直没有索引到期望值。为了防止一直自旋下去,cpu会设置一定的阈值,超过阈值后就会挂起这个线程,让出cpu。
3.3 举例
/**
* 演示带版本Stamp的AtomicStampedReference使用
* compareAndSet方法,需要指定老的版本号,如果设置成功返回true,否则返回false
* @author 45027056
*
*/
public class UseAtomicReferenceWithStamp {
static String name = "luke";
AtomicStampedReference atomicStampedReference = new AtomicStampedReference(name,0);
public static void main(String[] args) {
UseAtomicReferenceWithStamp demo = new UseAtomicReferenceWithStamp();
demo.new SuccessThread().start();
de mo.new FailThread().start();
System.out.println("local name is...:"+ name);
}
class SuccessThread extends Thread{
int oldStamp = atomicStampedReference.getStamp();
String oldReferenct = (String) atomicStampedReference.getReference();
@Override
public void run() {
boolean result = atomicStampedReference.compareAndSet(oldReferenct, "joe1", 0, 1);
System.out.println("refernce is :" + atomicStampedReference.getReference());
System.out.println("stamp is :" + atomicStampedReference.getStamp());
System.out.println("result is :" + result);
}
}
class FailThread extends Thread{
int oldStamp = atomicStampedReference.getStamp();
String oldReferenct = (String) atomicStampedReference.getReference();
@Override
public void run() {
boolean result = atomicStampedReference.compareAndSet(oldReferenct, "joe2", 0, 1);
System.out.println("refernce is" + atomicStampedReference.getReference());
System.out.println("stamp is" + atomicStampedReference.getStamp());
System.out.println("result is :" + result);
}
}
}
3.CAS原子操作的更多相关文章
- CAS原子操作实现无锁及性能分析
CAS原子操作实现无锁及性能分析 Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csdn.net/chen19870707 ...
- CAS 原子操作
理会CAS和CAS: 有时候面试官面试问你的时候,会问,谈谈你对CAS的理解,这时应该有很多人,就会比较懵,当然,我也会比较懵,当然我和很多人的懵不同,很多人可能,并不知道CAS是一个什么东西,而在我 ...
- 原子操作cas
一.概念, 基于处理器指令,把比较和交换合成一个指令完成,保证了原子性: 因为是针对一个内存地址值的,一个内存地址指向一个变量,所以只对一个共享变量能保证原子性: 二.原子操作类 锁只有synchro ...
- 锁&锁与指令原子操作的关系 & cas_Queue
锁 锁以及信号量对大部分人来说都是非常熟悉的,特别是常用的mutex.锁有很多种,互斥锁,自旋锁,读写锁,顺序锁,等等,这里就只介绍常见到的, 互斥锁 这个是最常用的,win32:CreateMute ...
- Java锁与CAS
一.加锁与无锁CAS 在谈论无锁概念时,总会关联起乐观派与悲观派,对于乐观派而言,他们认为事情总会往好的方向发展,总是认为坏的情况发生的概率特别小,可以无所顾忌地做事,但对于悲观派而已,他们总会认为发 ...
- 转:Java中的cas
引自:https://blog.csdn.net/mmoren/article/details/79185862 本篇的思路是先阐明无锁执行者CAS的核心算法原理然后分析Java执行CAS的实践者Un ...
- java并发编程(十三)----(JUC原子类)引用类型介绍(CAS和ABA的介绍)
这一节我们将探讨引用类型原子类:AtomicReference, AtomicStampedRerence, AtomicMarkableReference.AtomicReference的使用非常简 ...
- 基于 CAS 无锁实现的 Disruptor.NET 居然慢于 BlockingCollection,是真的吗?
StackOverflow 有人说自己的Disruptor.NET 代码比 BlockingCollection 还有慢 2 倍,并且把完整代码贴出,楼下几个老外也的回复说了一堆,但是没研究出个所以然 ...
- Java性能 -- CAS乐观锁
synchronized / Lock / CAS synchronized和Lock实现的同步锁机制,都属于悲观锁,而CAS属于乐观锁 悲观锁在高并发的场景下,激烈的锁竞争会造成线程阻塞,而大量阻塞 ...
随机推荐
- android 百度天气接口
百度天气接口 之前有篇随笔是说中国气象的天气接口的,但那个接口不是很稳定,用一段时间过后就会获取不到数据了. 随笔地址:http://www.cnblogs.com/liangstudyhome/p/ ...
- EF 完成指定数据迁移
Update-Database -ConfigurationTypeName Bmw.Services.DealerService.WebApiHost.MigrationsOfDealerDB.De ...
- 十六、Node.js-fs模块-流
10. fs.createReadStream 从文件流中读取数据 /** * 之前我们学习过读取文件内容的方法readFile():该方法适合读取文件内容比较少的文件,如果遇到数据量庞大的文件,我们 ...
- <select>标签默认值设置
<td> <label>操作类型:</label> <select id="operation_type" class="com ...
- subset子集全排序问题
思路一 可以用递推的思想,观察S=[], S =[1], S = [1, 2] 时解的变化. 可以发现S=[1, 2] 的解就是 把S = [1]的所有解末尾添上2,然后再并上S = [1]里面的原有 ...
- day6学python 生成器迭代器+压缩文件
生成器迭代器+压缩文件 readme的规范 1软件定位,软件的基本功能2运行代码的方法:安装环境,启动命令3简要的使用说明4代码目录结构说明,更详细点可以说明软件的基本原理5常见问题说明 ====== ...
- kali linux之操作系统识别/SMB扫描
操作系统识别技术种类很多,好产品采用多种技术结合 查看TTL值: linux:64(1-64) 某些unix:255 windows:128(65-128) nmap 被动操作系统识别 p0f ——— ...
- 洛谷P3358 最长k可重区间集问题(费用流)
传送门 因为一个zz错误调了一个早上……汇点写错了……spfa也写错了……好吧好像是两个…… 把数轴上的每一个点向它右边的点连一条边,容量为$k$,费用为$0$,然后把每一个区间的左端点向右端点连边, ...
- 堆排序 思想 JAVA实现
已知数组 79.52.48.51.49.34.21.3.26.23 ,请采用堆排序使数组有序. “什么是堆” 堆是一颗完全二叉树,N层完全二叉树是一颗,除N-1层外其节点数都达到最大,且第N层子节点全 ...
- linux的发行版
Linux的不同版本以及应用领域 1.Linux内核及发行版介绍 <1>Linux内核版本 内核(kernel)是系统的心脏,是运行程序和管理像磁盘和打印机等硬件设备的核心程序,它提供了一 ...