面试常问CAS和ABA问题,你懂了吗?
  TEZNKK3IfmPf 2024年03月30日 52 0

一、什么是CAS

        CAS(Compare-and-Swap)顾名思义,叫做比较和交换,大概执行过程是什么样呢?假设现有两个寄存器A、B和一个内存M,通过对寄存器A中的值与内存M的值进行比较是否相同,来决定寄存器B中的值是否与内存中M的值进行交换,若不相同则不会发生什么,若相同则将寄存器B的值与内存M的值进行交换;

CAS的伪代码:

class AtomicInteger {
    private int value;
    public int getAndIncrement() {
        int oldValue = value;
        while ( CAS(value, oldValue, oldValue+1) != true) {
            oldValue = value;
       }
        return oldValue;
   }
}
  • oldValue相当于寄存器A,int oldValue = value是把内存value的值读取到读取到寄存器A中;
  • getAndIncrement()这个方法相当于count++;(count相当于计数器)
  • oldValue + 1也把可以理解为是另一个寄存器B的值;
  • while循环是干什么的?通过比较value这个内存中的值,是否和寄存器A中的值相等,若相同,就把交换寄存器B和内存M的值(着重点是:寄存器B的值,设置到value中),同时返回true结束循环;如果不相同,CAS返回false,进入循环体中,重新读取内存value的值,放入寄存器A中;

        总结:CAS是CPU的一条指令,原子性完成的,线程安全,效率也很高;


二、CAS的应用——实现自旋锁

        自旋锁原理:当锁被其他线程拥有时,另外的线程不会挂起等待,而是会反复询问,看当前锁是否被释放,整个过程为纯用户态的轻量级锁;

伪代码:(注释详情)

public class SpinLock {
    private Thread owner = null;//表示当前锁是谁的
    public void lock(){ 
        while(!CAS(this.owner, null, Thread.currentThread())){
            //比较owner的值与null是否相同(null表示解锁状态),若owner的值为null
            //就把当前调用lock的线程的值设置到owner中(成功加锁),并结束循环;
            //若owner不为null,则CAS不进行交换,返回false,进入循环,再次进入判断;
       }
   }
    public void unlock (){
        this.owner = null;
   }
}

三、ABA问题

什么是ABA问题?

        内存中的值由A变为B,又变回A,CAS进行内存与寄存器值比较时,并未察觉变化;

        CAS中出现ABA问题,大多数情况下不会有问题,但极端情况下也可能出现问题,举个栗子:假设你去自动取款机中取钱,你的账户里有1000元,你准备从卡里去除500元,但是由于取款卡了一下,你以为自己没点上,所以又多点了一下,此时取款机就创建出两个线程都基于CAS来进行扣款操作,正好凑巧,此时你的好友也往你的账户上转了500元,于是等取款机反应过来,机子上显示的剩余存款的数据还是500元;以上情形就导致了多扣了一次500元,也就是极端情况下的BUG;

如何解决ABA问题?

        可以通过一个记录,来保存内存的修改次数,或者是记录上一次的修改时间;

        这时,就可以通过比较查看上一次修改的时间或者是修改次数,来观察到是否出现了ABA问题导致的BUG;

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2024年03月30日 0

暂无评论

TEZNKK3IfmPf