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的更多相关文章

  1. 并发和多线程(二)--线程安全、synchronized、CAS简介

    线程安全性: 当多个线程访问一个类的时候,这个类始终表示出正确的行为,那么这个类是线程安全的. 无状态的对象一定是线程安全的,例如大部分service.dao.Servlet都是无状态的. 线程安全体 ...

  2. CAS导致的ABA问题及解决:时间戳原子引用AtomicReference、AtomicStampedReference

    1.CAS导致ABA问题: CAS算法实现一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并交换,那么在这个时间差中会导致数据的变化. 比如:线程1从内存位置V中取出A,这时线程2也从V中取出A ...

  3. AtomicReference、AtomicStampedReference 和 AtomicMarkableReference

    这三个都是自 JDK1.5 开始加入到 java.util.concurrent.atomic 下面的.他们都可以在 lock-free 的情况下以原子的方式更新对象引用. 一.AtomicRefer ...

  4. 【Java并发编程】9、非阻塞同步算法与CAS(Compare and Swap)无锁算法

    转自:http://www.cnblogs.com/Mainz/p/3546347.html?utm_source=tuicool&utm_medium=referral 锁(lock)的代价 ...

  5. Java多线程之原子性 volatile、atomicInteger测试

    原文链接:http://www.cnblogs.com/zhengbin/p/5653051.html 一.补充概念 1.什么是线程安全性? <Java Concurrency in Pract ...

  6. java里的锁总结(synchronized隐式锁、Lock显式锁、volatile、CAS)

    一.介绍 首先, java 的锁分为两类: 第一类是 synchronized 同步关键字,这个关键字属于隐式的锁,是 jvm 层面实现,使用的时候看不见: 第二类是在 jdk5 后增加的 Lock ...

  7. JAVA CAS原理、unsafe、AQS

    concurrent包的实现 由于java的CAS同时具有 volatile 读和volatile写的内存语义,因此Java线程之间的通信现在有了下面四种方式: A线程写volatile变量,随后B线 ...

  8. 深入介绍Java中的锁[原理、锁优化、CAS、AQS]

    1.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 2.锁实现的基本原理 2.1.volatile Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新, ...

  9. Java中的锁[原理、锁优化、CAS、AQS]

    1.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 2.锁实现的基本原理 2.1.volatile Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新, ...

  10. Java中的锁原理、锁优化、CAS、AQS详解!

    阅读本文大概需要 2.8 分钟. 来源:jianshu.com/p/e674ee68fd3f 一.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 二.锁实现的基本原理 2.1.v ...

随机推荐

  1. Kotlin 与 JAVA 不同之处

    添加kotlin混编支持 要在Android项目中添加Kotlin混编支持,需要进行以下步骤: 在项目的 build.gradle 文件中添加以下代码: kotlin android { ... // ...

  2. Dijkstra(迪杰斯特拉)算法C++实现&讲解

    Dijkstra迪杰斯特拉算法及C++实现 Dijkstra算法是典型的最短路径路由算法,用来计算一个节点到其他所有节点的最短路径.算法的基本思想和流程是:1. 初始化出发点到其它各点的距离dist[ ...

  3. What's the best way to read and understand someone else's code?

    Find one thing you know the code does, and trace those actions backward, starting at the end Say, fo ...

  4. ILLA Cloud: 调用 Hugging Face Inference Endpoints,开启大模型世界之门

    一个月前,我们 宣布了与 ILLA Cloud 与达成的合作,ILLA Cloud 正式支持集成 Hugging Face Hub 上的 AI 模型库和其他相关功能. 今天,我们为大家带来 ILLA ...

  5. 安装MinGW,使用vscode进行C++编译

    1.下载 https://osdn.net/projects/mingw/downloads/68260/mingw-get-setup.exe/ 2.安装 直接默认所有选项安装即可,可以更换安装位置 ...

  6. Linux网络管理入门

    根据自己的需要来设置Linux的一些属性 网络状态查看 在终端输入ifconfig可以查看网络状态 # ifconfig eth0: flags=4163<UP,BROADCAST,RUNNIN ...

  7. ARL:资产侦察灯塔系统

    资产灯塔,不仅仅是域名收集 功能简介 "挖洞神器"资产安全灯塔(ARL),旨在快速侦察与目标关联的互联网资产,构建基础资产信息库. 协助甲方安全团队或者渗透测试人员有效侦察和检索资 ...

  8. Flutter(十) 音频+视频播放

    在Flutter中,我们有各种插件可供使用,从而实现音频和视频的播放功能. 例如,可以使用"text_to_speech"插件来将文字转换为语音,使用内置的"video_ ...

  9. 【Docker】安装及部署

    一.Ubuntu使用apt安装Docker 官方安装文档:https://docs.docker.com/engine/install/ubuntu/ 1.准备安装环境 [root@Docker-Ub ...

  10. 谁想和我一起做低代码平台!一个可以提升技术,让简历装x的项目

    序言 正如文章标题所述,最近一段时间低代码这个概念非常的火,但其实在不了解这个东西的时候觉得它真的很炫酷,从那时就萌生了做一个低代码平台的想法. 但随着时间的变化,现在市面上低代码各个业务方向的平台都 ...