android 面试题 CAS

本文详细解析了比较和交换(CAS)指令在多线程环境中的作用,以及Java利用CAS实现原子操作的具体方式,包括AtomicInteger类的使用示例和源码分析。

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

首先弄清楚什么是cas:

在计算机科学中,比较和交换(Conmpare And Swap)是用于实现多线程同步的原子指令。 它将内存位置的内容与给定值进行比较,只有在相同的情况下,将该内存位置的内容修改为新的给定值。 这是作为单个原子操作完成的。 原子性保证新值基于最新信息计算; 如果该值在同一时间被另一个线程更新,则写入将失败。 操作结果必须说明是否进行替换; 这可以通过一个简单的布尔响应(这个变体通常称为比较和设置),或通过返回从内存位置读取的值来完成(摘自维基本科)

在jdk后引入了一个很重要的包 java.util.concurrent.atomic

在这个包下很多类比如:AtomicInteger AtomicLong等就是为了多线程操作变量,线看下例子

package thread;
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerDemo {
    public static void main(String[] args) {
        //主内存的值
        AtomicInteger atomicInteger = new AtomicInteger(5);
       boolean isUpdate =  atomicInteger.compareAndSet(5,2019);
       System.out.println("-->"+atomicInteger.get());
        System.out.println("isUpdate-->"+isUpdate);
    }
}

首先主内存中的值是5 比如有二个线程t1和t2,那么在t1,t2中的工作内存的值都是从主内存拷贝过去的,也就是说t1,t2中的值都是5 ,那么这个时候t1线程对其进行修改,修改成2019,这个时候t1工作内存就把这个值刷新到主内存,主内存判断这个期望的值和主内存的值一样,那么就修改主内存中的值 为2019

看下源码:

 /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

我们可以看到

Atomically sets the value to the given updated value if the current value {@code ==} the expected value

这个解释,就是说如果这个当前期望的值和设置的atomic的值相等就更新新的值

 大厂都喜欢问底层实现原理,那么如果是面试肯定会问,它是怎么实现的?

package thread;
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerDemo {
    public static void main(String[] args) {
        //主内存的值
        AtomicInteger atomicInteger = new AtomicInteger(5);
        System.out.println("atomicInteger-->"+atomicInteger.getAndIncrement());
    }
}

点击getAndIncrement()方法进入到源码中,

/**
     * Atomically increments by one the current value.
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

它三个参数分别是:

this:表示当前类

valueOffset: 内存偏移量(内存地址)

1:就是常量了

发现getAndIncrement()方法是由unsafe对象调用的,而unsafe对象的创建:

private static final Unsafe unsafe = Unsafe.getUnsafe();

进入Unsafe类后是调用了:

public final int getAndAddInt(java.lang.Object o, long l, int i) { /* compiled code */ }

Unsafe是CAS的核心类,由于Java方法无法访问底层系统,需要通过本地(native)方法来访问,Unsafe相当于一个后门,基于该类可以直接操作特定内存的数据,Unsafe类存在与com.misc包下,其内部方法操作可以像C的指针一样操作内存,因为Java中的CAS操作依赖于Unsafe类的方法

 

CAS的全称是Compare. And.  Swap 它是一条CPU并发原语,

CAS并发原语体现在Java语言当中的sun.misc.Unsafe类中的各个方法,调用CAS中的方法,JVM会帮助我们实现CAS的汇编指令,这是一个完整依赖硬件的功能,通过它实现了Java中的原子操作,

 

CAS缺点:

1:循环时间长,开销大  因为底层使用了do...while操作

2:只能保证一个共享变量的原子操作

3:引出ABA问题?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值