小工具知识网

当前位置: 首页 > 行业知识 > 【Java基础】CAS (Compare And Swap) 操作

行业知识

【Java基础】CAS (Compare And Swap) 操作

2026-11-07 22:00:43 来源:互联网转载

关于作者:CSDN内容合伙人、���术专家, 从零开始做日活千万级APP。

专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。

目录

  • 一、导读
  • 二、概览
  • 三、使用场景
  • 四、原理
  • 五、优劣
    • 5.1 缺点:
    • 5.2 优点
    • 六、 推荐阅读

      一、导读

      我们继续总结学习Java基础知识,温故知新。

      二、概览

      CAS其实就是Compare And Swap的一个缩写,顾名思义就是比较并交换,其实就是把当前值与你预期的值进行一个比较,是一种用于在多线程环境下实现同步功能的机制。

      CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。 如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值 。否则,处理器不做任何操作。

      CAS是原子性的操作(读和写两者同时具有原子性),是让CPU比较内存中某个值是否和预期的值相同,如果相同则将这个值更新为新值,不相同则不做更新.

      对比交换是一条CPU的原子指令,其实现方式是基于硬件平台的汇编指令。

      CAS操作是原子性的,所以多线程并发使用CAS更新数据时,可以不使用锁。

      使用volatile关键字可以保证可见性和有序性,但是却没有原子性,比如a++,引入cas就可以解决多线程的原子性问题。

      CAS配合volatile来实现许多高并发类

      三、使用场景

      Java中利用CAS的乐观锁、原子性的特性高效解决了多线程的安全性问题。

      CAS这种方式适用于并发量不高的情况。

      四、原理

      实现方式是通过借助C/C++调用CPU指令完成的,是一条CPU的原子指令,依赖于系统。

      CAS的实现主要在JUC中的atomic包,存放在 java.util.concurrent.atomic 类路径下

      如:自增长 AtomicInteger 等

      Java中的CAS操作的执行依赖于Unsafe类,我们看下AtomicInteger的代码:

      public class AtomicInteger extends Number implements java.io.Serializable {    private static final Unsafe unsafe = Unsafe.getUnsafe();        private volatile int value;          public AtomicInteger(int initialValue) {        value = initialValue;    }    public final boolean compareAndSet(int expect, int update) {        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);    }    }

      CAS配合volatile来实现多线程可见性有序性和原子性。

      再看下Unsafe类

          public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

      我们进入Unsafe类的native方法compareAndSwapInt,调用UnSafe类中的CAS方法,JVM会帮我们实现出CAS汇编指令,这是一种完全依赖于硬件的功能,通过它实现了原子操作。

      由于CAS是一种系统原语,原语属于操作系统用于范畴,是由若干条指令组成,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS操作是一条CPU的原子指令,不会造成所谓的数据不一致的问题,所以说CAS是线程安全的。

      假如一个线程操作数据,干了一半活,累了,想要去休息。(貌似今天的线程体质都不太好)。于是它记录下当前数据的状态(就是数据的值),回家睡觉了。 醒来后打算继续接着干活,但是又担心数据可能被修改了,于是就把睡觉前保存的数据状态拿出来和现在的数据状态比较一下,如果一样,说明自己在睡觉期间,数据没有被人动过(当然也有可能是先被改成了其它,然后又改回来了,这就是ABA问题了),那就接着继续干。如果不一样,说明数据已经被修改了,那之前做的那些操作其实都白瞎了,就干脆放弃,从头再重新开始处理一遍。

      所以CAS这种方式适用于并发量不高的情况,也就是数据被意外修改的可能性较小的情况。如果并发量很高的话,你的数据一定会被修改,每次都要放弃,然后从头再来,这样反而花费的代价更大了,还不如直接加锁呢。

      五、优劣

      5.1 缺点:

      1. 循环时间长开销大(CAS自旋操作):当内存地址V与预期值B不相等时会一直循环比较,直到相等
      2. 只能保证一个共享变量的原子操作,不能保证代码块的原子性。
      3. 存在ABA问题

      并发1(上):获取出数据的初始值是A,后续计划实施CAS乐观锁,期望数据仍是A的时候,修改才能成功

      并发2:将数据修改成B

      并发3:将数据修改回A

      并发1(下):CAS乐观锁,检测发现初始值还是A,进行数据修改

      并发1在修改数据时,虽然还是A,但已经不是初始条件的A了,

      中间发生了A变B,B又变A的变化,此A已经非彼A,数据却成功修改,

      可能导致错误,这就是CAS引发的所谓的ABA问题。

      优化ABA问题:

      “版本号”的比对,一个数据一个版本,版本变化,即使值相同,也不应该修改成功。

      很好解决,再加一个版本号字段就行了,并规定只要修改数据,必须使版本号加1。

      5.2 优点

      • 没有引用锁的概念,并发量不高情况下提高效率
      • 减少线程上下文切换

        六、 推荐阅读

        【Java基础】原子性、可见性、有序性

        【Java基础】java可见性之 Happens-before

        【Java基础】java-android面试Synchronized

        【Java基础】java-android面试-线程状态

        【Java基础】线程相关

        【Java基础】java 异常

        【Java基础】java 反射

        【Java基础】java 泛型

        【Java基础】java注解

        【Java基础】java动态代理

        【Java基础】Java SPI

        【Java基础】Java SPI 二 之 Java APT

        【Java基础】 jvm 堆、栈、方法区 & java 内存模型

        【Java基础】volatile关键字

        【Java基础】CountDownLatch

上一篇:back单词怎么拼读?

下一篇:服务器散热背板怎么安装?