栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java面试之CAS

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java面试之CAS

面试时候经常被面试官灵魂三问:什么是CAS?原理是什么?有什么弊端?

 接下来,让我们给他说道说道。

进入正题:

1. 什么是 CAS?

CAS(Compare-And-Swap)是比较并交换的意思,它是一条 CPU 并发原语,用于判断内存中某个值是否为预期值,如果是则更改为新的值,这个过程是原子的。

 CAS机制当中使用了3个值:内存地址V,旧的预期值A,计算后要修改的新值B

  1.  两个线程同时对内存值V进行操作,V初始值为1
  2. 线程1、线程2都对V加1计算,预期值A=1,新值B=2
  3. 线程2先提交,预期值A==V,更新成功,将V更新为2
  4. 线程1提交时4,发现预期值A=1,V=2,A!=V,提交失败,重新获取内存值V=2
  5. 线程1自旋,V=2,A=2,B=3,重新比较A==V成立,然后更新V=3,最后V=3结束

总结

更新一个变量的时候,只有当变量的预期值 A 和内存地址 V 中的实际值相同时,才会将内存地址 V 对应的值修改为 B,这个操作就是CAS

2. CAS 基本原理

CAS 主要包括两个操作:Compare和Swap。

CAS 是一条 CPU 的原子指令,执行必须是连续的,执行过程中不允许被中断。

JDK 是在 1.5 版本后才引入 CAS 操作,在sun.misc.Unsafe这个类中定义了 CAS 相关的方法

    
    public final native boolean compareAndSwapObject(Object o, long offset,
                                                     Object expected,
                                                     Object x);

    
    public final native boolean compareAndSwapInt(Object o, long offset,
                                                  int expected,
                                                  int x);

    
    public final native boolean compareAndSwapLong(Object o, long offset,
                                                   long expected,
                                                   long x);

3. Java 中的应用

CAS主要封装在java并发编程工具包中,java.util.concurrent包

  AtomicInteger 类解决 i++ 非原子性问题,通过volatile 关键字和 CAS 操作来实现

查看下源码:

    public final int getAndUpdate(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return prev;
    }

    public final int updateAndGet(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return next;
    }

    

    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

4. 弊端
  • 典型的ABA 

ABA 是 CAS 操作的一个经典问题,一个变量初始值为 A,修改为 B,然后又修改为 A,这个变量实际被修改过了,但是 CAS 操作无法感知到。

解决这个问题也很简单,只要在变量前加版本号,每次变量更新了就把版本号加1

 

  • 自旋开销

CAS 出现冲突后就会开始重复尝试,即自旋操作,如果资源竞争非常激烈,自旋长时间不能成功就会给 CPU 带来非常大的开销。

优化:限制自旋的次数,避免过度消耗 CPU;

  • 只能保证单个变量的原子性

当对一个共享变量执行操作时,可以使用 CAS 来保证原子性,如果要对多个共享变量进行操作时,CAS 是无法保证原子性的,比如需要将 i 和 j 同时加 1:

i++;j++;

优化:

1、使用 synchronized 进行加锁;

2、将多个变量操作合成一个变量操作。AtomicReference 类来保证引用对象之间的原子性,把多个变量放在一个对象里来进行CAS操作

 AtomicReference 关键方法:

    
    public final boolean compareAndSet(V expect, V update) {
        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
    }

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/340551.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号