Java面试3-能谈下CAS机制吗?

文章介绍了Java中的CAS(CompareAndSwap)机制,一种用于保证多线程环境下共享变量修改的原子性的技术。通过Unsafe类的compareAndSwapInt方法实现,虽然存在底层的内存读写操作,但通过Lock指令确保了原子性。CAS常用于J.U.C库中的并发数据结构如Atomic和AQS等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CAS是Java中Unsafe类里面的方法,它的全称是Compare And Swap,比较并交换的意思。它的主要功能是能够保证在多线程环境下,对于共享变量的修改的原子性

有这样一个场景,有一个成员变量state,默认值是0,定义了一个方法doSomething(),这个方法的逻辑是,判断state是否为0,如果为0,就修改成1。这个逻辑看起来没有任何问题,但是在多线程环境下,会存在原子性的问题,因为这里是典型的Read-Write的操作。
一般情况下,我们会在doSomething()这个方法上加同步锁来解决原子性问题,但是加同步锁会带来性能上的损耗,所以对于这类场景,就可以使用CAS机制来进行优化。

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 (Exception ex) {
            throw new Error(ex);
        }
    }

    public void doSomething() {
        if (unsafe.compareAndSwapInt(this, stateOffset, 0, 1)) {
            // TODO
        }
    }
}

doSomething()方法中,我们调用了unsafe类的compareAndSwapInt()方法来达到同样的目的,这个方法有四个参数,分别是:当前对象实例、成员变量state在内存地址中的偏移量、预期值0、期望更改之后的值1。CAS机制会比较state内存地址偏移量和传入的预期值0是否相等,如果相等,就直接修改内存地址中state的值为1。否则,返回false,表示修改失败,而这个过程是原子的,不会存在线程安全问题
CompareAndSwap是一个native方法,实际上它最终还是会面临同样的问题,就是先从内存地址中读取state的值,然后去比较,最后再修改。这个过程不管在什么层面上实现,都会存在原子性问题。所以呢,CompareAndSwap的底层实现中,在多核CPU环境中,会增加一个Lock指令对缓存或者总线加锁,从而保证比较并替换这两个指令的原子性。
CAS主要用在并发场景中,比较典型的使用场景有两个:

  1. J.U.C里面Atomic的原子实现,比如AtomicInteger、AtomicLong。
  2. 实现多线程对共享资源竞争的互斥性质,比如在AQS、ConcurrentHashMap、ConcurrentLinkedQueue等都有用到。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值