CAS的实现原理
CAS的全称是CompareAndSwap,比较并交换,是Java保证原子性的一种重要方法,也是一种乐观锁的实现方式。
它需要先提前一步获取旧值,然后进入此方法比较当下的值是否与旧值相同,如果相同,则更新数据,否则退出方法,重复一遍刚才的动作。由此可见,CAS方法是非堵塞的。CAS方法需要三个参数,变量内存值、旧的预期值、数据更新值
CAS的伪代码可以表示为:
do{
获取备份旧数据;
准备更新的数据;
}while( !CAS( 内存地址,备份的旧数据,新数据 ))
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
上面是原子类AtomicInteger的局部源码,可以看出来Java中的CAS操作都是由Sun包下的Unsafe类实现的,而unsafe类中的方法都是Native方法,都是由JVM本地实现。
然后简单去网上找了找相关的openJDK源码,它调用了Atomic:comxchg方法,这个方法的实现放在了hotspot下的os_cpu包中的,也就是说它调用了操作系统和CPU层级的东西。
经过进一步了解获知,这个方法在Linux x86系统的多处理器情况下是通过调用LOCK指令来实现的,立刻写会内存且令其他缓存行失效。
CAS的问题:
1、ABA问题,比如刚开始读取到备份是3,然后被其他线程连续修改两次,最终结果还是3,那么CAS很可能识别不到数据发生了改变,这种情况对程序造成了极大的安全隐患。可以通过添加版本号等标志位来解决该问题。
2、循环时间长开销大,如果长时间自旋不成功,会给CPU带来很大开销。可以使用自适应自旋锁解决这个问题
3、只能保证一个共享变量的原子操作。比如AtomicInteger都是每次只能对一个变量进行原子性控制。
单次CAS操作的开销:

这是一个8核CPU的计算机系统,先简单介绍一下CPU的硬件结构体系。每个CPU都有一个高速缓存区Cache(寄存器),每两个CPU之间有一段互联模块可以让管芯内的两个核可以互相通信,最中间还有个系统互联模块可以让四个管芯进行通讯。数据以“缓存线”为单位在系统中传输,缓存线对应内存中2的整数幂的一个字节块
计算机系统中,当CPU要获取一个变量值的时候,必须要将包含了该变量的缓存线保存到自己的寄存器中;CPU要向主存写入值的时候,根据缓存一致性协议,必须保证其他CPU获知此操作,或者让其他CPU删除该缓存线的拷贝。
因此,如果CPU1和CPU5同时持有一个变量的缓存线,然后CPU5想进行CAS操作,那么它需要访问CPU5、6的互联模块,未找到持有该缓存线的CPU,然后访问系统级的互联模块,发现第一处互联模块有该缓存线,继而访问第一处互联模块,最终找到了CPU1。此时才算是完成了大部分操作。因此如果从最优角度考虑,CAS所花费的时钟周期较锁来说要小很多。
在Java中,sun.misc.Unsafe类提供了硬件级别的院子操作来实现这个CAS,JUC包下的大量类都使用了这个Unsafe.java类的CAS操作。
CAS的实现原理的更多相关文章
- Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。
精彩理解: https://www.jianshu.com/p/21be831e851e ; https://blog.csdn.net/heyutao007/article/details/19 ...
- (转载)java高并发:CAS无锁原理及广泛应用
java高并发:CAS无锁原理及广泛应用 版权声明:本文为博主原创文章,未经博主允许不得转载,转载请注明出处. 博主博客地址是 http://blog.csdn.net/liubenlong007 ...
- CAS单点登录原理以及debug跟踪登录流程
CAS 原理和协议 基础模式 基础模式 SSO 访问流程主要有以下步骤: 1. 访问服务: SSO 客户端发送请求访问应用系统提供的服务资源. 2. 定向认证: SSO 客户端会重定向用户请求到 SS ...
- Springboot security cas整合方案-原理篇
前言:网络中关于Spring security整合cas的方案有很多例,对于Springboot security整合cas方案则比较少,且有些仿制下来运行也有些错误,所以博主在此篇详细的分析cas原 ...
- CAS单点登录原理简单介绍
1. SSO简介 1.1 单点登录定义 单点登录(Single sign on),英文名称缩写SSO,SSO的意思就是在多系统的环境中,登录单方系统,就可以在不用再次登录的情况下访问相关受信任的系统. ...
- CAS单点登录原理解析
转自: https://www.cnblogs.com/lihuidu/p/6495247.html 1.基于Cookie的单点登录的回顾 基于Cookie的单点登录核心原理: 将用户名 ...
- CAS单点登录原理
转自 https://www.cnblogs.com/lihuidu/p/6495247.html 1.基于Cookie的单点登录的回顾 基于Cookie的单点登录核心原理: 将用户名密 ...
- CAS单点登录原理解析(转载)
1.基于Cookie的单点登录的回顾 基于Cookie的单点登录核心原理: 将用户名密码加密之后存于Cookie中,之后访问网站时在过滤器(filter)中校验用户权限,如果没有权限则从 ...
- CAS 跨域原理
http://www.blogjava.net/rain1102/articles/227739.html CAS(Central Authentication Service) 是 Yale 大学发 ...
- 解决并发问题的CAS思想及原理
全称为:Compare and swap(比较与交换),用来解决多线程并发情况下使用锁造成性能开销的一种机制: 原理思想:CAS(V,A,B),V为内存地址,A为预期原值,B为新值.如果内存地 ...
随机推荐
- HDU1686 Oulipo 题解 KMP算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1686 题目大意:给你一个子串t和一个母串s,求s中有多少个子串t. 题目分析:KMP模板题. cal_ ...
- www的iptables实例
#!/bin/bash export PATH=/sbin:/usr/sbin:/bin:/usr/bin #加载相关模块 modprobe iptable_nat modprobe ip_nat_f ...
- Python--day28--面试题
- pytorch nn.LSTM()参数详解
输入数据格式:input(seq_len, batch, input_size)h0(num_layers * num_directions, batch, hidden_size)c0(num_la ...
- tf.reduce_sum()函数
1234567reduce_sum 是 tensor 内部求和的工具.其参数中: input_tensor 是要求和的 tensor axis 是要求和的 rank,如果为 none,则表示所有 ra ...
- css元素居中的几种方式
1.水平居中 <div style="width:200px;margin:0 auto;background-color: yellow;">水平居中</div ...
- 读《Effect Java中文版》
读<Effect Java中文版> 译者序 序 前言 第1章引言 1 第2章创建和销毁对象 4 第1条:考虑用静态工厂方法代替构造函数 4 第2条:使用私有构造函数强化singleto ...
- vue-learning:32 - component - 异步组件和工厂函数
异步组件 只有在这个组件需要使用的时候才从服务器加载这一个组件模块,用于渲染,并且会把结果缓存起来供未来复用. 实现方法: 组件定义的时候,以一个工厂函数的形式传入,在需要组件的执行这个函数,然后将组 ...
- Hamcrest Tutorial
Java Hamcrest Home Hamcrest Tutorial Introduction Hamcrest is a framework for writing matcher object ...
- AutoHotKey 用打码的快捷键
本文告诉大家如何使用 AutoHotKey 将 - 键默认输入的时候是下划线,因为使用下划线在写代码的时候是用在私有字段,而 - 很少使用 我打码经常需要使用下划线_而下划线需要按shift+- 两个 ...