CAS的原理

CAS(Compare-And-Swap 或 Compare-And-Set)是一种用于实现并发编程中无锁(lock-free)数据结构的原子操作。CAS 操作比较内存中的某个位置的当前值是否等于预期值,如果相等,则将其更新为新的值,否则不更新。整个过程是一个原子操作,不会被中断,从而避免了线程同步中的竞争和死锁问题。

CAS 的原理

CAS 操作包含三个操作数:

  1. 内存位置(V,Variable):需要更新的变量的内存地址。
  2. 期望值(A,Expected):当前线程认为这个变量应该具有的值。
  3. 新值(B,New):如果变量的当前值等于期望值,那么需要将变量更新为的新值。

CAS 操作的逻辑如下:

  • 如果内存位置 V 的当前值等于期望值 A,那么将内存位置 V 的值更新为新值 B,返回 true 表示更新成功。
  • 否则,不做任何操作,返回 false 表示更新失败。

CAS 的步骤

  1. 读取变量 V 的当前值。
  2. 比较变量 V 的当前值和期望值 A。
  3. 如果变量 V 的当前值等于期望值 A,将其更新为新值 B。
  4. 如果变量 V 的当前值不等于期望值 A,不进行更新。

这个过程是通过底层硬件的原子指令支持来实现的,因此是线程安全的。

CAS 的优点

  1. 无锁并发:通过 CAS 操作,可以实现无锁的数据结构,从而避免了传统锁机制带来的开销和死锁问题。
  2. 高效:在大多数情况下,CAS 操作比使用锁进行同步更加高效,特别是在多线程竞争不激烈的情况下。

CAS 的缺点

  1. ABA 问题:如果变量 V 的值从 A 变成 B,又变回 A,CAS 操作无法检测到这种变化,从而误认为没有发生变化。ABA 问题可以通过版本号解决,即每次更新变量时同时更新版本号。
  2. 自旋等待:在高竞争环境下,如果多个线程频繁失败并重试 CAS 操作,会导致大量的 CPU 消耗。
  3. 复杂性:相较于使用锁,编写和维护 CAS 操作的代码更为复杂。

Java 中的 CAS 实现

Java 提供了 java.util.concurrent.atomic 包中的类来支持 CAS 操作,如 AtomicIntegerAtomicBooleanAtomicReference 等。这些类内部使用了 Unsafe 类的 CAS 方法来实现原子操作。

示例:AtomicInteger 的 CAS 操作
import java.util.concurrent.atomic.AtomicInteger;

public class CASExample {
    public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger(0);

        int expectedValue = 0;
        int newValue = 1;

        boolean success = atomicInteger.compareAndSet(expectedValue, newValue);

        System.out.println("CAS operation success: " + success);
        System.out.println("Current value: " + atomicInteger.get());
    }
}

解决 ABA 问题

Java 提供了 AtomicStampedReference 类来解决 ABA 问题。它在进行 CAS 操作时,不仅比较值,还比较一个额外的标记(stamp)。

示例:使用 AtomicStampedReference 解决 ABA 问题
import java.util.concurrent.atomic.AtomicStampedReference;

public class ABAExample {
    public static void main(String[] args) {
        AtomicStampedReference<Integer> atomicStampedRef = new AtomicStampedReference<>(100, 0);

        int[] stampHolder = new int[1];
        Integer currentValue = atomicStampedRef.get(stampHolder);
        int currentStamp = stampHolder[0];

        int newValue = 101;
        int newStamp = currentStamp + 1;

        boolean success = atomicStampedRef.compareAndSet(currentValue, newValue, currentStamp, newStamp);

        System.out.println("CAS operation success: " + success);
        System.out.println("Current value: " + atomicStampedRef.get(stampHolder) + ", Current stamp: " + stampHolder[0]);
    }
}

总结

CAS 是一种高效的无锁并发机制,通过硬件支持的原子操作来实现线程安全。虽然 CAS 有一些缺点,但在合适的场景中,CAS 可以提供比锁更好的性能和可扩展性。Java 提供了丰富的 CAS 支持类,开发者可以方便地使用这些类来实现高效的并发程序。

相关推荐

  1. CAS原理

    2024-07-18 11:04:02       27 阅读
  2. GitLab CI/CD原理及应用详解(一)

    2024-07-18 11:04:02       23 阅读
  3. GitLab CI/CD原理及应用详解(四)

    2024-07-18 11:04:02       22 阅读
  4. GitLab CI/CD原理及应用详解(三)

    2024-07-18 11:04:02       26 阅读
  5. GitLab CI/CD原理及应用详解(五)

    2024-07-18 11:04:02       30 阅读
  6. GitLab CI/CD原理及应用详解(二)

    2024-07-18 11:04:02       31 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-18 11:04:02       70 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-18 11:04:02       74 阅读
  3. 在Django里面运行非项目文件

    2024-07-18 11:04:02       62 阅读
  4. Python语言-面向对象

    2024-07-18 11:04:02       72 阅读

热门阅读

  1. P5717 【深基3.习8】三角形分类

    2024-07-18 11:04:02       21 阅读
  2. 【数据平台-dataworks】-问题总结

    2024-07-18 11:04:02       23 阅读
  3. spring中的依赖注入

    2024-07-18 11:04:02       21 阅读
  4. 力扣212题:单词搜索 II

    2024-07-18 11:04:02       21 阅读
  5. Go语言学习

    2024-07-18 11:04:02       22 阅读
  6. Spring Boot集成ShardingSphere详解

    2024-07-18 11:04:02       21 阅读
  7. 石油与化工行业的工业互联网平台革新之路

    2024-07-18 11:04:02       23 阅读