【面试题】能聊聊你对CAS的理解以及其底层实现原理可以吗?

本文探讨了在多线程环境下,如何通过CAS(Compare and Set)解决并发安全问题。CAS操作是原子性的,避免了传统锁机制带来的性能损失。然而,CAS也存在ABA问题、无限循环(自旋)和多变量原子性问题。为解决这些问题,Java并发包提供了AtomicStampedReference和LongAdder等工具类。

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

当多个线程要访问同一个数据时,包括取值、询问、修改时,必然会出现多线程并发安全问题

public class MyObject{
    int i = 0;
    public synchronized void increment(){
        //同一时间,只有一个线程可以进入当前方法
        //在一个对象实例的方法上加synchronized
        i++;
    }
}

调用:
MyObject mo = new MyObject();
mo.increment();

这种加锁的方式是串行化,执行效率不高。多线程情况下,需要排队执行increment方法

 

使用并发包下的AtomicInteger类(底层基于CAS来进行实现)

public class MyObject{
    AtomicInteger i = new AtomicInteger(0);
    public  void increment(){
        //多个线程此时来执行这段代码
        //不需要synchronized加锁,也是线程安全的
        i.incrementAndGet();
    }
}

CAS全称 compare and set,CAS操作是原子的,底层会进行硬件之别的上锁,中间是不可以被打断的

(1)先读取当前值,假设i=0

(2)i++

(3)尝试设置i=1:先对比预期值是否为0,如果为0则设置i=1;

cas(v,expected,newValue)

    if(v==expected)

        v = newValue;

线程1与线程2同时调用incrementAndSet方法,只有一个线程能完成CAS。

CAS在底层的硬件级别保证一定是原子的,同一时间只有一个线程可以执行CAS,先比较再设置,其他线程的CAS同时间去执行,此时会失败。

假设:线程1成功CAS,线程2在CAS过程中发现值不对,会重新读取当前值,再次尝试CAS

AtomicXX类底层的实现原理实际上是CAS

 

【评论区】

CAS虽然高效的解决了原子操作问题,但仍然存在三大问题

1.ABA问题:如果变量V初次读取的时候值是A,后来变成了B,然后又变成了A,你本来期望的值是第一个A才会设置新值,第二个A跟期望不符合,但却也能设置新值。针对这种情况,java并发包中提供了一个带有标记的原子引用类AtomicStampedReference,它可以通过控制变量值的版本号来保证CAS的正确性,比较两个值的引用是否一致,如果一致,才会设置新值。但使用AtomicStampedReference就可以很好的解决这个问题。

2.无限循环问题(自旋):看源码可知,Atomic类设置值的时候会进入一个无限循环,只要不成功,就会不停的循环再次尝试。在高并发时,如果大量线程频繁修改同一个值,可能会导致大量线程执行compareAndSet()方法时需要循环N次才能设置成功,即大量线程执行一个重复的空循环(自旋),造成大量开销。解决无限循环问题可以使用java8中的LongAdder,分段CAS和自动分段迁移

3.多变量原子问题:只能保证一个共享变量的原子操作。一般的Atomic类,只能保证一个变量的原子性,但如果是多个变量呢?可以用AtomicReference,这个是封装自定义对象的,多个变量可以放一个自定义对象里,然后他会检查这个对象的引用是不是同一个。如果多个线程同时对一个对象变量的引用进行赋值,用AtomicReference的CAS操作可以解决并发冲突问题。 但是如果遇到ABA问题,AtomicReference就无能为力了,需要使用AtomicStampedReference来解决。

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值