Java CAS:AtomicInteger、AtomicReference、AtomicStampedReference
Java CAS:AtomicInteger、AtomicReference、AtomicStampedReference
什么是CAS?
什么是CAS? 即比较并替换,实现并发算法时常用到的一种技术。CAS操作包含三个操作数——内存位置、预期原值及新值。执行CAS操作的时候,将内存位置的值与预期原值比较,如果相匹配,那么处理器会自动将该位置值更新为新值,否则,处理器不做任何操作。我们都知道,CAS是一条CPU的原子指令(cmpxchg指令),不会造成所谓的数据不一致问题,Unsafe提供的CAS方法(如compareAndSwapXXX)底层实现即为CPU指令cmpxchg。
* CAS
* @param o 包含要修改field的对象
* @param offset 对象中某field的偏移量
* @param expected 期望值
* @param update 更新值
* @return true | false
*/
public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object update);
public final native boolean compareAndSwapInt(Object o, long offset, int expected,int update);
public final native boolean compareAndSwapLong(Object o, long offset, long expected, long update);

AtomicInteger:
AtomicInteger代表着基本类型的原子类:其中有AtomicInteger、AtomicBoolean、AtomicLong等.

其中AtomicInter继承 Number 实现 Serializable接口

应用
方法:
1)public AtomicInteger();//初始化该类。初始值为0
2)public AtomicInteger( int initialValue) //给定初始值的初始化
在程序中需要原子的增加或减少计数器时,使用此类 AtomicInteger
public class Counter{
private AtomicInteger ia = new AtomicInteger();
public void increase(){
ia.getAndIncrement();
}
public int get(){
return ia.get();
}
}
public class Worker extends Thread{
Counter counter;
public Worker( Counter counter){
this.counter = counter;
}
public void run (){
for(int i=0;i<100;i++){
counter.increase();
}
}
}
public class Index{
public static void main(String[] args){
Counter counter = new Counter(0;
Thread t1 = new Worker(counter);
Thread t2 = new Worker(counter);
t1.start();
t2.start();
try{
t1.jion();
t2.jion();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("counter.get() = " + counter.get());
}
}
AtomicReference
上面讲到AtomicInteger对一个共享变量执行操作时,CAS能够保证原子操作,但是对多个共享变量操作时,CAS是无法保证操作的原子性的。
Java从1.5开始JDK提供了AtomicReference类来保证引用对象之间的原子性,可以把多个变量放在一个对象里来进行CAS操作。

方法:
// 用V来指明应用的类型
public AtomicReference() // 用初始值null创建类AmoticReference的实例。
public AtomicReference( V initialValue) // 用初始initialValue 创建类AtomicReference的实例,
//举例
public class Counter(){
private AtomicReference<Integer> af = new AtomicReference<Integer>(0);
public void increase(){
Integer temp = af.get();
af.comparseAndSet( temp,temp+1);
}
public Integet get(){
return af.get();
}
}
public class Worker extends Thread{
Counter counter;
public Worker( Counter counter){
this.counter = counter;
}
public void run (){
for(int i=0;i<100;i++){
counter.increase();
}
}
}
public class Index{
public static void main(String[] args){
Counter counter = new Counter(0;
Thread t1 = new Worker(counter);
Thread t2 = new Worker(counter);
t1.start();
t2.start();
try{
t1.jion();
t2.jion();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("counter.get() = " + counter.get());
}
}
AtomicStampedReference
是什么?首先需要了解一下ABA问题
ABA问题是指在CAS操作中带来的潜在问题
CAS意思是 compare and swap 或者 compare and set , 对于一个要更新的变量A,我们提供一个它的旧值a 和新值 b ,如果变量A的值等于旧值 那么更新成功, 否则失败。
举例:
比如两个线程
- 线程1 查询A的值为a,与旧值a比较,
- 线程2 查询A的值为a,与旧值a比较,相等,更新为b值
- 线程2 查询A的值为b,与旧值b比较,相等,更新为a值
- 线程1 相等,更新B的值为c
可以看到这样的情况下,线程1 可以正常 进行CAS操作,将值从a变为c 但是在这之间,实际A值已经发了a->b b->a的转换
仔细思考,这样可能带来的问题是,如果需要关注A值变化过程,是会漏掉一段时间窗口的监控
另外:cas本身不是锁,只是cas很容易用来封装成锁,乐观锁只是一种思想,并不是真的有一种锁是乐观的。有些场景是不封装成锁直接使用cas,例如对AtomicInteger的increase,这就是乐观锁思想的实践,所以AtomicInteger.increase才能被称为无锁实现。
问题解决
JDK从1.5开始提供了AtomicStampedReference类来解决ABA问题,具体操作封装在compareAndSet()中。compareAndSet()首先检查当前引用和当前标志与预期引用和预期标志是否相等,如果都相等,则以原子方式将引用值和标志的值设置为给定的更新值。
Java CAS:AtomicInteger、AtomicReference、AtomicStampedReference的更多相关文章
- 并发和多线程(二)--线程安全、synchronized、CAS简介
线程安全性: 当多个线程访问一个类的时候,这个类始终表示出正确的行为,那么这个类是线程安全的. 无状态的对象一定是线程安全的,例如大部分service.dao.Servlet都是无状态的. 线程安全体 ...
- CAS导致的ABA问题及解决:时间戳原子引用AtomicReference、AtomicStampedReference
1.CAS导致ABA问题: CAS算法实现一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并交换,那么在这个时间差中会导致数据的变化. 比如:线程1从内存位置V中取出A,这时线程2也从V中取出A ...
- AtomicReference、AtomicStampedReference 和 AtomicMarkableReference
这三个都是自 JDK1.5 开始加入到 java.util.concurrent.atomic 下面的.他们都可以在 lock-free 的情况下以原子的方式更新对象引用. 一.AtomicRefer ...
- 【Java并发编程】9、非阻塞同步算法与CAS(Compare and Swap)无锁算法
转自:http://www.cnblogs.com/Mainz/p/3546347.html?utm_source=tuicool&utm_medium=referral 锁(lock)的代价 ...
- Java多线程之原子性 volatile、atomicInteger测试
原文链接:http://www.cnblogs.com/zhengbin/p/5653051.html 一.补充概念 1.什么是线程安全性? <Java Concurrency in Pract ...
- java里的锁总结(synchronized隐式锁、Lock显式锁、volatile、CAS)
一.介绍 首先, java 的锁分为两类: 第一类是 synchronized 同步关键字,这个关键字属于隐式的锁,是 jvm 层面实现,使用的时候看不见: 第二类是在 jdk5 后增加的 Lock ...
- JAVA CAS原理、unsafe、AQS
concurrent包的实现 由于java的CAS同时具有 volatile 读和volatile写的内存语义,因此Java线程之间的通信现在有了下面四种方式: A线程写volatile变量,随后B线 ...
- 深入介绍Java中的锁[原理、锁优化、CAS、AQS]
1.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 2.锁实现的基本原理 2.1.volatile Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新, ...
- Java中的锁[原理、锁优化、CAS、AQS]
1.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 2.锁实现的基本原理 2.1.volatile Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新, ...
- Java中的锁原理、锁优化、CAS、AQS详解!
阅读本文大概需要 2.8 分钟. 来源:jianshu.com/p/e674ee68fd3f 一.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 二.锁实现的基本原理 2.1.v ...
随机推荐
- JS - new Function
Function 在JavaScript当中,除了可以使用function或箭头函数定义方法外,还可以使用new Function的形式动态创建函数,此时与eval()方法类似 创建一个不接收参数的方 ...
- 一次线上OOM问题的个人复盘
原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,非公众号转载保留此声明. 上个月,我们一个java服务上线后,偶尔会发生内存OOM(Out Of Memory)问题,但由于OOM导致服务 ...
- Java面向对象--接口和多态
final 关键字 最终修饰符 可以修饰 类 方法 变量 被final修饰后不能被继承 重写 二次赋值 修饰类时 该类不可以被继承 修饰方法时 该方法不能被重写 修饰变量时, 该变量只能赋值一次, 不 ...
- vue指令之属性指令
目录 属性指令 示例 属性指令 标签上的属性可以绑定变量,变量变化,属性也会变化 # 什么是属性?比如: href/src/name/value/class/style... 语法: v-bind:属 ...
- 强大的 apt-get 命令
强大的 apt-get 命令(小结) 一.ubuntu下管理软件最方便的非 apt-get 工具莫属了,它的常见用法稍微整理一下供以后参考(详细见 man apt-get ): 1.更新源,升级软件和 ...
- SELinux入门学习总结
前言 安全增强型 Linux(Security-Enhanced Linux)简称 SELinux,它是一个 Linux 内核模块,也是 Linux 的一个安全子系统. SELinux 主要由美国国家 ...
- [数据结构]二叉搜索树(BST) VS 平衡二叉排序树(AVL) VS B树(平衡多路搜索树) VS B+树 VS 红黑树(平衡二叉B树)
1 二叉排序树/二叉查找树/Binary Sort Tree 1种对排序和查找都很有用的特殊二叉树 叉排序树的弊端的解决方案:平衡二叉树 二叉排序树必须满足的3条性质(或是具有如下特征的二叉树) 若它 ...
- 数据泵:impdp导入用户ORA-01653
,问题描述:在导入一个用户数据的时候,大小为14G左右,导进来的时候卡半天,后来发现是表空间满了,已经恢复了大概6G左右,剩下8G左右没有恢复.此时磁盘剩余19G,加了15G的表空间,磁盘就剩下4G左 ...
- Web界面元素的测试
文本框 测试点 输入正常的字母或数字 输入超长字符.例如在"名称"框中输入超过允许边界个数的字符,假设最多255个字符,尝试输入256个字符,检查程序能否正确处理 输入默认值,空白 ...
- 从原理聊JVM(一):染色标记和垃圾回收算法
作者:京东科技 康志兴 1 JVM运行时内存划分 1.1 运行时数据区域 • 方法区 属于共享内存区域,存储已被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码等数据.运行时常量池,属于方法 ...