龙空技术网

什么是Java的CAS(Compare-And-Swap)操作?

从程序员到架构师 111

前言:

现在你们对“java 重写compare”都比较注意,大家都需要知道一些“java 重写compare”的相关资讯。那么小编同时在网上网罗了一些对于“java 重写compare””的相关内容,希望小伙伴们能喜欢,你们一起来了解一下吧!

CAS(Compare-And-Swap,即比较并交换)是在Java中的一种用于实现无锁并发的操作,尤其在并发编程中,CAS操作被广泛用于避免传统的锁(如 synchronized)引入的性能开销,下面我们就详细介绍一下CAS操作。

什么是 CAS?

CAS是一种原子操作,主要用于解决多线程环境下的竞争问题。它包括三个参数

V:表示变量的当前值(在内存中的值)。E:期望的值(希望变量当前持有的值)。N:新值(希望将变量更新为的新值)。

CAS操作的工作过程如下

第一步、检查变量的当前值 V 是否等于期望的值E。第二步、如果V == E,则将变量的值更新为N。第三步、如果V != E,说明该变量的值已被其他线程修改,CAS操作不会更新该变量的值,而是直接返回当前的变量值。

这种操作在硬件层面保证是原子性的,即不会被中断。

Java中的CAS应用

Java提供了sun.misc.Unsafe类来实现底层的CAS操作,CAS操作在Java的 java.util.concurrent.atomic包(如 AtomicInteger, AtomicBoolean, AtomicReference 等)中有大量使用。它们利用 CAS操作来实现无锁的原子性变量更新。

为什么CAS高效?

相比锁机制,CAS操作无需将线程挂起或唤醒,因此能有效减少线程上下文切换的开销。它的非阻塞特性使其在高并发场景下具备很好的性能优势。

CAS的局限性

CAS也有一些局限性和缺点

ABA 问题:如果一个值由A -> B -> A变化过,CAS检查值是否未变化时会误判,认为变量没有被修改。Java提供了AtomicStampedReference 来解决这个问题。自旋消耗CPU:CAS操作会反复尝试更新值,直到成功为止,如果线程竞争激烈,CAS操作会不断重试,浪费CPU资源。只能保证一个变量的原子操作:CAS只能用于单个变量的原子操作,无法直接处理多个变量的原子性,复杂的多变量一致性操作还是需要依赖锁。

下面是一个简单的CAS示例,使用AtomicInteger来实现计数器的原子性更新。

import java.util.concurrent.atomic.AtomicInteger;public class CASExample {    public static void main(String[] args) {        AtomicInteger atomicCounter = new AtomicInteger(0);        // 模拟多线程环境下的 CAS 操作        for (int i = 0; i < 1000; i++) {            new Thread(() -> {                int oldValue;                int newValue;                do {                    oldValue = atomicCounter.get(); // 获取当前值                    newValue = oldValue + 1; // 新值为当前值加一                } while (!atomicCounter.compareAndSet(oldValue, newValue)); // CAS 操作            }).start();        }        // 输出结果        System.out.println("Final counter value: " + atomicCounter.get());    }}

在这个代码中,atomicCounter 使用了 compareAndSet 方法来保证在多线程下计数器的更新操作是线程安全的。

总结

CAS是Java并发编程中的重要技术,通过原子操作实现无锁并发,具有高效、非阻塞的优势。然而,它也有ABA问题、自旋开销大以及只能作用于单变量等缺陷。Java的java.util.concurrent.atomic包中提供了封装好的CAS操作类,简化了开发者在并发环境下的操作,使得编写无锁、线程安全的代码更加容易。

标签: #java 重写compare