面试必问的CAS,你懂多少?

一、什么是CAS?

CAS(Compare And Swap),即比较并交换,是一种用于实现多线程同步的原子操作指令。

二、工作原理

CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。CAS 指令执行时,当且仅当内存位置的值与预期原值相等时,将内存位置的值修改为新值,否则什么都不做。这个过程是原子性的,即这个操作在执行过程中不会被中断。
例如,在一个多线程环境下,多个线程同时尝试修改一个共享变量。线程首先读取共享变量的当前值作为预期原值,然后在进行修改时,使用 CAS 操作将共享变量的当前值与预期原值进行比较,如果相等,则将共享变量的值更新为新值,否则重新读取共享变量的值并尝试再次修改,直到成功为止。

三、优点

非阻塞性:与传统的锁机制不同,CAS 操作在执行失败时不会阻塞线程,而是让线程重新尝试,避免了线程阻塞和唤醒带来的开销,提高了系统的并发性。
原子性:CAS 操作是原子性的,能够保证在多线程环境下对共享变量的操作是安全的,不会出现数据不一致的情况。

四、缺点

ABA 问题:如果一个值从 A 变为 B,又从 B 变回 A,那么使用 CAS 操作时可能无法察觉这个变化,从而导致错误的结果。解决这个问题的方法通常是使用带有版本号的原子类,每次修改时版本号加一,这样就可以避免 ABA 问题。
解决:
① 使用 AtomicStampReference 类,增加了一个标记 stamp,可以判断数据有没有被修改过。

public class AtomicStampedReference<V> {

    private static class Pair<T> {
        final T reference;
        final int stamp;
        private Pair(T reference, int stamp) {
            this.reference = reference;
            this.stamp = stamp;
        }
        static <T> Pair<T> of(T reference, int stamp) {
            return new Pair<T>(reference, stamp);
        }
    }

② 可以使用版本号,其实和上面stamp原理差不多。
循环开销大:在高并发的情况下,如果多个线程同时竞争一个共享变量,可能会导致 CAS 操作不断失败,从而使线程进入长时间的循环等待,消耗大量的 CPU 资源。

五、应用场景

CAS 操作在 Java 中的 java.util.concurrent.atomic 包下被广泛应用,例如 AtomicInteger、AtomicLong、AtomicReference 等原子类都是通过 CAS 操作来实现线程安全的。这些原子类在多线程环境下可以安全地进行自增、自减、赋值等操作,而不需要使用传统的锁机制。此外,CAS 操作还可以用于实现无锁数据结构,如无锁栈、无锁队列等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_30885871

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值