CAS是什么
CAS是什么?
比较并交换
例子1:
public class ABADemo1 {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(5);
System.out.println(atomicInteger.compareAndSet(5,2019)+"\t当前值是:"+atomicInteger.get());
System.out.println(atomicInteger.compareAndSet(5,1024)+"\t当前值是:"+atomicInteger.get());
}
}
结果如下:

CAS底层原理?
1.自旋锁
2.UnSafe类
atomicInteger.getAndIncrement();
底层调用的其实是unsafe方法,关系见下图:


va1 AtomicInteger对象本身。
var2 该对象的引用地址。
var4 需要变动的数量。
var5 是用var1 var2找出的主内存中真实的值,用该对象当前的值与var5比较,如果相同,更新var5+var4并且返回true,如果不同,继续取值然后再比较,直到更新完成。(自旋)

最后通过native调用本地方法,该方法的实现位于unsafe.cpp中。
1.Unsafe类:
是CAS的核心类,由于Java方法无法直接访问底层系统,需要通过本地方法(native)来访问,Unsafe相当于一个后门,基于该类可以直接操作特定内存的数据。Unsafe类存在于sun.misc包中,其内部方法操作可以像C的指针一样直接操作内存,因为java 中CAS的操作执行依赖于Unsafe类的方法。
注意Unsafe类中的所有方法都是native修饰的,也就是说Unsafe类中的方法都直接调用操作系统底层资源执行相应任务
2.变量valueOffset,表示该变量值在内存中的偏移地址,因为Unsafe就是根据内存偏移地址来获取数据的。
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
3.变量vaue用volatile修饰,保证了多线程之间的内存可见性。
CAS 的全称为Compare-And-Swap,它是一条CPU并发原语。
它的功能是判断内存某个位置的值是否为预期值,这个过程是原子的
CAS并发原语体现在Java语言就是sun.misc.Unsafe类中的各个方法。调用UnSafe类中的CAS方法,JVM会帮我们实现CAS汇编指令。这是一种完全依赖于硬件的功能。通过它实现了原子操作。再次强调,由于CAS是一种系统原语,原语属于操作系统用于范畴,是由若干条指令组成的,用于完成某个功能的一个过程,并且原语的执行必须是连续的,再执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致问题。
CAS 的缺点
1.循环时间长开销很大。
2.只能保证一个共享变量的原子操作。
3.会有ABA问题。
CAS会导致"ABA问题"
CAS算法实现一个重要前提需要取出内存中某时刻的数据并再当下时刻比较并替换,那么再这个时间差会导致数据的变化。
比如说一个线程one从内存位置V中取出A,这时候另一个线程two也从内存中取出A,并且线程two进行了一些操作将值变成了B,然后线程two又将V位置的数据变成A, 这时候线程one进行CAS操作发现内存中仍然是A,然后线程one操作成功。尽管线程one的CAS操作成功,但不代表这个操作过程就是没有问题的。
AtomicReference原子引用例子:
@Getter
@ToString
@AllArgsConstructor
class User {
String userName;
int age;
} /**
* AtomicReference原子引用,想对某个类进行包装,可以参考这个类的写法
*/
public class AtomicReferenceDemo { public static void main(String[] args) {
User z3 = new User("z3",22);
User li4 = new User("li4",25);
AtomicReference<User> atomicReference = new AtomicReference<>();
atomicReference.set(z3);
System.out.println(atomicReference.compareAndSet(z3,li4)+"\t"+atomicReference.get().toString());
System.out.println(atomicReference.compareAndSet(z3,li4)+"\t"+atomicReference.get().toString());
}
} 运行结果见下图:

解决ABA问题 加版本号例子:
public class ABADemo {
static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100,1);
public static void main(String[] args) {
System.out.println("-------------存在ABA问题");
new Thread(() ->{
atomicReference.compareAndSet(100,101);
atomicReference.compareAndSet(101,100);
},"T1").start();
new Thread(() ->{
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicReference.compareAndSet(100,2019) +"\t" +atomicReference.get());
},"t2").start();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-------------以下是解决ABA问题");
new Thread(() ->{
int stamp = atomicStampedReference.getStamp();
System.out.println(Thread.currentThread().getName()+"\t第1次版本号"+stamp);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
atomicStampedReference.compareAndSet(100,101,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
System.out.println(Thread.currentThread().getName()+"\t第2次版本号"+atomicStampedReference.getStamp());
atomicStampedReference.compareAndSet(101,100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
System.out.println(Thread.currentThread().getName()+"\t第3次版本号"+atomicStampedReference.getStamp());
},"t3").start();
new Thread(() ->{
int stamp = atomicStampedReference.getStamp();
System.out.println(Thread.currentThread().getName()+"\t第1次版本号"+stamp);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean result = atomicStampedReference.compareAndSet(100,2019,stamp,stamp+1);
System.out.println(Thread.currentThread().getName()+"\t修改成功否"+result+"\t 当前版本号"+atomicStampedReference.getStamp());
System.out.println(Thread.currentThread().getName()+"\t当前实际最新值"+atomicStampedReference.getReference());
},"t4").start();
}
}
运行结果见下图:

CAS是什么的更多相关文章
- .NET应用和AEAI CAS集成详解
1 概述 数通畅联某综合SOA集成项目的统一身份认证工作,需要第三方系统配合进行单点登录的配置改造,在项目中有需要进行单点登录配置的.NET应用系统,本文专门记录.NET应用和AEAI CAS的集成过 ...
- SuperMap-iServer-单点登录功能验证(CAS)
SuperMap-iServer-单点登录功能验证(CAS) 1.测试目的: 验证SuperMap-iServer使用CAS单点登录的功能是否正常. 2.测试环境: SuperMap-iServer8 ...
- 集成基于CAS协议的单点登陆
相信大家对单点登陆(SSO,Single Sign On)这个名词并不感到陌生吧?简单地说,单点登陆允许多个应用使用同一个登陆服务.一旦一个用户登陆了一个支持单点登陆的应用,那么在进入其它使用同一单点 ...
- 【Java并发编程实战】-----“J.U.C”:CAS操作
CAS,即Compare and Swap,中文翻译为"比较并交换". 对于JUC包中,CAS理论是实现整个java并发包的基石.从整体来看,concurrent包的实现示意图如下 ...
- 多线程同步工具——CAS原子变量
这是我参考的一篇文章<基于CAS的乐观锁实现>,讲述的是一种需要CPU支持的执行技术CAS(Compare and Swap). 首先理解什么是原子性操作,意思是不能再拆分的操作,例如改写 ...
- CAS FOR WINDOW ACTIVE DIRECTORY SSO单点登录
一.CAS是什么? CAS(Central Authentication Service)是 Yale 大学发起的一个企业级的.开源的项目,旨在为 Web 应用系统提供一种可靠的单点登录解决方法(支持 ...
- CAS Client集群环境的Session问题及解决方案
[原创申明:文章为原创,欢迎非盈利性转载,但转载必须注明来源] 之前写过一篇文章,介绍单点登录的基本原理.这篇文章重点介绍开源单点登录系统CAS的登录和注销的实现方法.并结合实际工作中碰到的问题,探讨 ...
- cas单点登录搭建
Cas Server下载:http://developer.jasig.org/cas/ Cas Client下载:http://developer.jasig.org/cas-clients/ 测试 ...
- CAS环境搭建
实验背景: 系统环境: Windows XP | SUN JDK1.6U4 | Tomcat6.0.14 | CAS Server 3.1.1 + CAS Client 2.1.1 主机完整名称: ...
- ovirt配置为cas登录
准备工作 Ovirt测试机.CAS服务器.AD服务器 cas.crt -- CAS服务器的CA证书 allwinner.cer -- CAS服务器的证书颁发机构根证书 Ovirt测试机要求:apach ...
随机推荐
- linux设备编号的内部表示
在内核中, dev_t 类型(在 <linux/types.h>中定义)用来持有设备编号 -- 主次部分都包 括. 对于 2.6.0 内核, dev_t 是 32 位的量, 12 位用作主 ...
- P1004 奶牛与牧场
题目描述 有一个牧场,牧场上的牧草每天都在匀速生长,这片牧场可供 \(a\) 头牛吃 \(b\) 天,或可供 \(c\) 头牛吃 \(d\) 天,那么,这片牧场每天新生的草量最多可供几头牛吃1天? 输 ...
- 【b503】篝火晚会
Time Limit: 1 second Memory Limit: 50 MB [问题描述] 佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了"小教官" ...
- vue-learning:12-vue获取模板内容的方式
vue获取模板内容的方式 目录 outerHTML获取内容 template属性获取内容 ES6的字符串模板 <template>标签 <srcipt type="text ...
- git 上传当前分支
因为我现在的分支是的名很长,每次需要上次当前分支需要写很多代码,是不是有很简单方法上传当前分支. 如果要上传一个分支到仓库 origin 那么就需要使用下面的命令 git push origin 分支 ...
- Docker应用容器引擎
1.Docker概述 1.1.Docker简介 Docker 是一个开源的应用容器引擎,基于 Go 语言开发.Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到 ...
- Destoon系统目录树SEO属性目录开发实例
如何在destoon里设置树形目录结构的SEO优化方式官方给的SEO伪静态实例是没有这个方式的 楼主后来想了一下,就干脆自己做一个吧,已经测试完全无误通过,特意分享给大家 目前比如sell模块下类别[ ...
- [DevExpress]treeList1背景色设置与自定义图标
为了和系统界面一致改成透明色: treeList1.BackColor = Color.Transparent; treeList1.Appearance.Empty.BackColor = Colo ...
- Appium+Pytest实现app并发测试
前言 这个功能已经写完很长时间了,一直没有发出来,今天先把代码发出来吧,有一些代码是参考网上写的,具体的代码说明今天暂时先不发了,代码解释的太详细还得我花点时间^_^, 毕竟想让每个人都能看明白也不容 ...
- wide&deep模型演化
推荐系统模型演化 LR-->GBDT+LR FM-->FFM-->GBDT+FM|FFM FTRL-->GBDT+FTRL Wide&DeepModel (Deep l ...
