CAS 机制

CAS 是 Java 中 Unsafe 类里面的方法,它的全称是 CompareAndSwap,比较并交换的意思。它的主要功能是能够保证在多线程环境下,对于共享变量的修改的原子性。
举个例子,比如说有这样一个场景,有一个成员变量 state,默认值是 0,定义了一个方法 doSomething(),这个方法的逻辑是,判断 state 是否为 0 ,如果为0,就修改成 1。这个逻辑看起来没有任何问题,但是在多线程环境下,会存在原子性的问题,因为这里是一个典型的,Read - Write 的操作。一般情况下,我们会在 doSomething()这个方法上加同步锁来解决原子性问题。

java 复制代码
public class Example {
    private int state=0;
    public void doSomething(){
        if (state==0) { //多线程环境中,存在原子性问题
            state=1;
        }
    }
}

但是,加同步锁,会带来性能上的损耗,所以,对于这类场景,我们就可以使用 CAS机制来进行优化.这个是优化之后的代码如下,在 doSomething()方法中,我们调用了 unsafe 类中的compareAndSwapInt()方法来 达到同样的目的,这个方法有四个参数,分别是:当前对象实例、成员变量 state 在内存地址中的偏移量、预期值 0、期望更改之后的值 1。CAS机制会比较 state内存地址偏移量对应的值和传入的预期值 0 是否相等,如果相等,就直接修改内存地址中 state 的值为1.否则,返回 false,表示修改失败,而这个过程是原子的,不会存在线程安全问题。

java 复制代码
public class Example {
    private volatile int state=0;
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long stateOffset;
    static {
        try {
            stateOffset = unsafe.objectFieldOffset(Example.class.getDeclaredField("state"));
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }
    public void doSomething(){
        if (unsafe.compareAndSwapInt(this,stateOffset,0,1)) {
            // TODO
        }
    }
}

CompareAndSwap 是一个 native 方法,实际上它最终还是会面临同样的问题,就是先从内存地址中读取 state 的值,然后去比较,最后再修改。这个过程不管是在什么层面上实现,都会存在原子性问题。所以呢,CompareAndSwap 的底层实现中,在多核 CPU 环境下,会增加一个 Lock指令对缓存或者总线加锁,从而保证比较并替换这两个指令的原子性。

CAS 主要用在并发场景中,比较典型的使用场景有两个:

  • 第一个是 J.U.C 里面 Atomic 的原子实现,比如 AtomicInteger,AtomicLong。
  • 第二个是实现多线程对共享资源竞争的互斥性质,比如在 AQS、ConcurrentHashMap、ConcurrentLinkedQueue 等都有用到。
相关推荐
cxyxiaokui0014 分钟前
JDK 动态代理 vs CGLIB:原理、区别与 Spring AOP 底层揭秘
java·后端·spring
代码充电宝23 分钟前
LeetCode 算法题【中等】189. 轮转数组
java·算法·leetcode·职场和发展·数组
我命由我1234526 分钟前
PDFBox - PDDocument 与 byte 数组、PDF 加密
java·服务器·前端·后端·学习·java-ee·pdf
花哥码天下30 分钟前
Oracle下载JDK无需登录
java·开发语言
摇滚侠1 小时前
Spring Boot 3零基础教程,yml语法细节,笔记16
java·spring boot·笔记
wei8440678721 小时前
本地项目第一次推送到gitee上的完整命令
java·android studio
星球奋斗者1 小时前
计算机方向如何才能更好的找到工作?(成长心得)
java·后端·考研·软件工程·改行学it
Jabes.yang1 小时前
互联网大厂Java面试:缓存技术与监控运维的深度探讨
java·面试指南·缓存技术·监控运维
海梨花1 小时前
【八股笔记】SSM
java·开发语言·笔记·后端·面试·框架
珹洺1 小时前
Java-Spring入门指南(二十五)Android 的历史,认识移动应用和Android 基础知识
android·java·spring