java中CAS是什么

发布时间:2021-07-29 09:02:19 作者:小新
来源:亿速云 阅读:620
# Java中CAS是什么

## 目录
1. [什么是CAS](#什么是cas)
2. [CAS的实现原理](#cas的实现原理)
3. [Java中的CAS实现](#java中的cas实现)
4. [CAS的典型应用场景](#cas的典型应用场景)
5. [CAS的优缺点](#cas的优缺点)
6. [ABA问题及解决方案](#aba问题及解决方案)
7. [CAS与锁的对比](#cas与锁的对比)
8. [总结](#总结)

## 什么是CAS

CAS(Compare And Swap,比较并交换)是一种无锁的原子操作机制,它是现代多线程并发编程中的重要概念。CAS操作包含三个操作数:
- 内存位置(V)
- 预期原值(A)
- 新值(B)

当且仅当内存位置V的值等于预期原值A时,处理器才会将该位置的值更新为新值B,否则不执行任何操作。无论哪种情况,都会返回该位置当前的值。

**CAS的核心思想**:先比较后修改,这个比较和修改的过程是一个原子操作。

## CAS的实现原理

CAS的实现依赖于底层硬件提供的原子性指令(如x86架构的`CMPXCHG`指令)。现代处理器通过以下方式支持CAS:

1. **总线加锁**:早期处理器通过总线锁保证原子性,但会阻塞其他处理器访问内存,性能较差
2. **缓存锁定**:现代处理器使用缓存一致性协议(如MESI)来保证原子性,只在缓存行级别加锁

Java通过`sun.misc.Unsafe`类提供CAS操作,其底层最终会调用本地方法(Native Method)实现:

```java
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);

Java中的CAS实现

1. Atomic原子类

Java在java.util.concurrent.atomic包中提供了一系列原子类,它们都基于CAS实现:

// 原子整型
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet(); // CAS实现的自增

// 原子引用
AtomicReference<String> ref = new AtomicReference<>("old");
ref.compareAndSet("old", "new");

2. Unsafe类

Unsafe类提供了硬件级别的原子操作(不推荐直接使用):

public class UnsafeExample {
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;
    
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
}

3. 锁的实现基础

AQS(AbstractQueuedSynchronizer)等并发工具类的底层也依赖CAS:

// AQS中的典型CAS操作
protected final boolean compareAndSetState(int expect, int update) {
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

CAS的典型应用场景

1. 计数器实现

public class CasCounter {
    private AtomicInteger count = new AtomicInteger(0);
    
    public int increment() {
        int oldValue, newValue;
        do {
            oldValue = count.get();
            newValue = oldValue + 1;
        } while (!count.compareAndSet(oldValue, newValue));
        return newValue;
    }
}

2. 非阻塞栈实现

public class ConcurrentStack<E> {
    AtomicReference<Node<E>> top = new AtomicReference<>();
    
    public void push(E item) {
        Node<E> newHead = new Node<>(item);
        Node<E> oldHead;
        do {
            oldHead = top.get();
            newHead.next = oldHead;
        } while (!top.compareAndSet(oldHead, newHead));
    }
    
    public E pop() {
        Node<E> oldHead, newHead;
        do {
            oldHead = top.get();
            if (oldHead == null) return null;
            newHead = oldHead.next;
        } while (!top.compareAndSet(oldHead, newHead));
        return oldHead.item;
    }
    
    private static class Node<E> {
        final E item;
        Node<E> next;
        // 构造方法...
    }
}

3. 乐观锁实现

数据库乐观锁的Java实现:

public class OptimisticLock {
    private AtomicInteger version = new AtomicInteger(0);
    
    public void updateWithLock(Data data) {
        int currentVersion = version.get();
        // 模拟业务处理
        process(data);
        // CAS更新版本号
        if (!version.compareAndSet(currentVersion, currentVersion + 1)) {
            throw new OptimisticLockException("并发修改冲突");
        }
    }
}

CAS的优缺点

优点

  1. 无锁并发:避免线程阻塞和上下文切换
  2. 高性能:在低竞争环境下性能显著优于锁
  3. 避免死锁:不存在锁的获取和释放问题

缺点

  1. ABA问题:值从A变为B又变回A,CAS会误认为没变化
  2. 循环时间长开销大:在高竞争环境下可能导致大量自旋
  3. 只能保证一个变量的原子性:对多个变量的操作需要额外处理

ABA问题及解决方案

ABA问题示例

线程1:读取值A
线程2:将值A改为B
线程2:将值B改回A
线程1:执行CAS,发现值仍是A,操作成功

解决方案

  1. 版本号机制(AtomicStampedReference)
AtomicStampedReference<String> ref = 
    new AtomicStampedReference<>("A", 0);

// 获取当前版本号
int stamp = ref.getStamp();
// 更新时检查值和版本号
ref.compareAndSet("A", "B", stamp, stamp + 1);
  1. 时间戳机制(扩展AtomicStampedReference思路)

  2. 布尔标记(在某些场景下可用)

CAS与锁的对比

特性 CAS
实现方式 乐观锁 悲观锁
线程阻塞 不会阻塞(自旋) 会阻塞
适用场景 低竞争、简单操作 高竞争、复杂操作
性能特点 无上下文切换开销 有上下文切换开销
内存开销 较小 较大(锁对象、监控等)
编码复杂度 较高(需处理失败情况) 相对简单

总结

CAS作为Java并发编程的重要机制,具有以下关键点: 1. 通过硬件指令实现无锁并发,提高性能 2. Java通过Atomic类和Unsafe提供CAS支持 3. 适用于计数器、栈等简单数据结构的并发控制 4. 需要注意ABA问题和自旋开销 5. 在高并发场景下可能需要结合其他并发控制手段

随着Java版本演进,JDK在CAS基础上发展出了更高级的并发工具(如LongAdder),但理解CAS原理仍然是掌握Java并发的关键基础。

”`

注:本文实际约2800字,要达到3400字可考虑: 1. 增加更多代码示例(如AtomicLongArray的使用) 2. 添加性能测试数据对比 3. 深入分析JDK各版本对CAS的优化 4. 扩展讨论CPU缓存行与CAS的关系 5. 增加与其他语言CAS实现的对比

推荐阅读:
  1. CAS是什么?
  2. Java CAS原理是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java cas

上一篇:如何解决基于python等频分箱qcut的问题

下一篇:JAVA中正则表达式有什么用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》