JDK 8 CAS(Compare-And-Swap)源码详解(详细注释版)

JDK 8 CAS(Compare-And-Swap)源码详解(详细注释版)

1. CAS基本概念

/*
 * CAS (Compare-And-Swap) 比较并交换
 * 是一种无锁的原子操作算法
 * CAS操作包含三个操作数:
 * - 内存位置(V)
 * - 预期原值(A) 
 * - 新值(B)
 * 
 * CAS操作的语义是:如果内存位置V的值等于预期原值A,则将内存位置V的值更新为新值B,
 * 否则不进行任何操作。整个比较和替换操作是原子性的。
 * 
 * CAS广泛应用于Java并发编程中,是实现无锁算法的基础。
 */

/**
 * CAS操作的基本流程:
 * 1. 获取当前内存位置的值
 * 2. 比较当前值与预期值是否相等
 * 3. 如果相等,则更新为新值
 * 4. 如果不相等,则不更新
 * 5. 返回操作是否成功
 */

2. Unsafe类中的CAS方法

/*
 * sun.misc.Unsafe类提供了底层的CAS操作
 * 这些方法直接调用CPU的CAS指令
 */
public final class Unsafe {
    
    /**
     * 比较并交换对象字段的int值
     * 
     * @param obj 对象实例
     * @param offset 字段在对象中的偏移量
     * @param expect 预期值
     * @param update 新值
     * @return 如果交换成功返回true,否则返回false
     */
    public final native boolean compareAndSwapInt(Object obj, long offset,
                                                  int expect, int update);
    
    /**
     * 比较并交换对象字段的long值
     * 
     * @param obj 对象实例
     * @param offset 字段在对象中的偏移量
     * @param expect 预期值
     * @param update 新值
     * @return 如果交换成功返回true,否则返回false
     */
    public final native boolean compareAndSwapLong(Object obj, long offset,
                                                   long expect, long update);
    
    /**
     * 比较并交换对象字段的引用值
     * 
     * @param obj 对象实例
     * @param offset 字段在对象中的偏移量
     * @param expect 预期引用
     * @param update 新引用
     * @return 如果交换成功返回true,否则返回false
     */
    public final native boolean compareAndSwapObject(Object obj, long offset,
                                                     Object expect, Object update);
    
    /**
     * 原子递增并获取int字段的值
     * 
     * @param obj 对象实例
     * @param offset 字段在对象中的偏移量
     * @param delta 增量
     * @return 递增后的新值
     */
    public final int getAndAddInt(Object obj, long offset, int delta) {
        int v;
        do {
            // 获取当前值
            v = getIntVolatile(obj, offset);
            // 循环CAS直到成功
        } while (!compareAndSwapInt(obj, offset, v, v + delta));
        return v;
    }
    
    /**
     * 原子递增并获取long字段的值
     * 
     * @param obj 对象实例
     * @param offset 字段在对象中的偏移量
     * @param delta 增量
     * @return 递增后的新值
     */
    public final long getAndAddLong(Object obj, long offset, long delta) {
        long v;
        do {
            // 获取当前值
            v = getLongVolatile(obj, offset);
            // 循环CAS直到成功
        } while (!compareAndSwapLong(obj, offset, v, v + delta));
        return v;
    }
    
    /**
     * 原子设置int字段的值并返回旧值
     * 
     * @param obj 对象实例
     * @param offset 字段在对象中的偏移量
     * @param newValue 新值
     * @return 旧值
     */
    public final int getAndSetInt(Object obj, long offset, int newValue) {
        int v;
        do {
            // 获取当前值
            v = getIntVolatile(obj, offset);
            // 循环CAS直到成功
        } while (!compareAndSwapInt(obj, offset, v, newValue));
        return v;
    }
    
    /**
     * 原子设置long字段的值并返回旧值
     * 
     * @param obj 对象实例
     * @param offset 字段在对象中的偏移量
     * @param newValue 新值
     * @return 旧值
     */
    public final long getAndSetLong(Object obj, long offset, long newValue) {
        long v;
        do {
            // 获取当前值
            v = getLongVolatile(obj, offset);
            // 循环CAS直到成功
        } while (!compareAndSwapLong(obj, offset, v, newValue));
        return v;
    }
    
    /**
     * 原子设置对象字段的引用值并返回旧引用
     * 
     * @param obj 对象实例
     * @param offset 字段在对象中的偏移量
     * @param newValue 新引用
     * @return 旧引用
     */
    public final Object getAndSetObject(Object obj, long offset, Object newValue) {
        Object v;
        do {
            // 获取当前引用
            v = getObjectVolatile(obj, offset);
            // 循环CAS直到成功
        } while (!compareAndSwapObject(obj, offset, v, newValue));
        return v;
    }
    
    // 以下是一些volatile访问方法
    public native int getIntVolatile(Object obj, long offset);
    public native void putIntVolatile(Object obj, long offset, int value);
    public native long getLongVolatile(Object obj, long offset);
    public native void putLongVolatile(Object obj, long offset, long value);
    public native Object getObjectVolatile(Object obj, long offset);
    public native void putObjectVolatile(Object obj, long offset, Object value);
    
    // 有序写入方法(不保证对其他线程立即可见)
    public native void putOrderedInt(Object obj, long offset, int value);
    public native void putOrderedLong(Object obj, long offset, long value);
    public native void putOrderedObject(Object obj, long offset, Object value);
}

3. AtomicInteger源码分析

/*
 * AtomicInteger是CAS应用的典型例子
 * 提供了原子性的int操作
 */
public class AtomicInteger extends Number implements java.io.Serializable {
    
    // 序列化版本UID
    private static final long serialVersionUID = 6214790243416807050L;
    
    // 获取Unsafe实例
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    
    // value字段的偏移量
    private static final long valueOffset;
    
    static {
        try {
            // 获取value字段在对象中的偏移量
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { 
            throw new Error(ex); 
        }
    }
    
    // 实际存储的int值,使用volatile保证可见性
    private volatile int value;
    
    /**
     * 构造方法 - 初始化为0
     */
    public AtomicInteger() {
    }
    
    /**
     * 构造方法 - 指定初始值
     * 
     * @param initialValue 初始值
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }
    
    /**
     * 获取当前值
     * 
     * @return 当前值
     */
    public final int get() {
        return value;
    }
    
    /**
     * 设置新值
     * 
     * @param newValue 新值
     */
    public final void set(int newValue) {
        value = newValue;
    }
    
    /**
     * 原子性地设置新值,并返回旧值
     * 
     * @param newValue 新值
     * @return 旧值
     */
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }
    
    /**
     * 原子性地比较并设置值
     * 如果当前值等于预期值,则更新为新值
     * 
     * @param expect 预期值
     * @param update 新值
     * @return 如果成功设置返回true,否则返回false
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
    
    /**
     * 弱化的比较并设置
     * 在某些平台可能不保证原子性,但通常与compareAndSet相同
     * 
     * @param expect 预期值
     * @param update 新值
     * @return 如果成功设置返回true,否则返回false
     */
    public final boolean weakCompareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
    
    /**
     * 原子性地递增并返回旧值
     * 
     * @return 递增前的值
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
    
    /**
     * 原子性地递减并返回旧值
     * 
     * @return 递减前的值
     */
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }
    
    /**
     * 原子性地增加指定值并返回旧值
     * 
     * @param delta 要增加的值
     * @return 增加前的值
     */
    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }
    
    /**
     * 原子性地递增并返回新值
     * 
     * @return 递增后的值
     */
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }
    
    /**
     * 原子性地递减并返回新值
     * 
     * @return 递减后的值
     */
    public final int decrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
    }
    
    /**
     * 原子性地增加指定值并返回新值
     * 
     * @param delta 要增加的值
     * @return 增加后的值
     */
    public final int addAndGet(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
    }
    
    /**
     * 原子性地更新值,使用给定的更新函数
     * 
     * @param updateFunction 更新函数
     * @return 更新后的值
     */
    public final int updateAndGet(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return next;
    }
    
    /**
     * 原子性地更新值,使用给定的更新函数,并返回旧值
     * 
     * @param updateFunction 更新函数
     * @return 更新前的值
     */
    public final int getAndUpdate(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return prev;
    }
    
    /**
     * 带内存语义的获取操作
     * 
     * @return 当前值
     */
    public final int getPlain() {
        return value;
    }
    
    /**
     * 带内存语义的设置操作
     * 
     * @param newValue 新值
     */
    public final void setPlain(int newValue) {
        value = newValue;
    }
    
    /**
     * 带volatile语义的获取操作
     * 
     * @return 当前值
     */
    public final int getOpaque() {
        return value;
    }
    
    /**
     * 带volatile语义的设置操作
     * 
     * @param newValue 新值
     */
    public final void setOpaque(int newValue) {
        value = newValue;
    }
    
    /**
     * 带release语义的设置操作
     * 
     * @param newValue 新值
     */
    public final void setRelease(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
    }
    
    /**
     * 带acquire语义的获取操作
     * 
     * @return 当前值
     */
    public final int getAcquire() {
        return value;
    }
}

4. AtomicReference源码分析

/*
 * AtomicReference提供对引用类型的原子操作
 */
public class AtomicReference<V> implements java.io.Serializable {
    
    private static final long serialVersionUID = -1848883965231344442L;
    
    // 获取Unsafe实例
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    
    // value字段的偏移量
    private static final long valueOffset;
    
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicReference.class.getDeclaredField("value"));
        } catch (Exception ex) { 
            throw new Error(ex); 
        }
    }
    
    // 实际存储的引用值,使用volatile保证可见性
    private volatile V value;
    
    /**
     * 构造方法 - 初始化为null
     */
    public AtomicReference() {
    }
    
    /**
     * 构造方法 - 指定初始值
     * 
     * @param initialValue 初始引用值
     */
    public AtomicReference(V initialValue) {
        value = initialValue;
    }
    
    /**
     * 获取当前引用值
     * 
     * @return 当前引用值
     */
    public final V get() {
        return value;
    }
    
    /**
     * 设置新引用值
     * 
     * @param newValue 新引用值
     */
    public final void set(V newValue) {
        value = newValue;
    }
    
    /**
     * 原子性地设置新引用值,并返回旧引用值
     * 
     * @param newValue 新引用值
     * @return 旧引用值
     */
    public final V getAndSet(V newValue) {
        return (V)unsafe.getAndSetObject(this, valueOffset, newValue);
    }
    
    /**
     * 原子性地比较并设置引用值
     * 如果当前引用值等于预期引用值,则更新为新引用值
     * 
     * @param expect 预期引用值
     * @param update 新引用值
     * @return 如果成功设置返回true,否则返回false
     */
    public final boolean compareAndSet(V expect, V update) {
        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
    }
    
    /**
     * 弱化的比较并设置
     * 
     * @param expect 预期引用值
     * @param update 新引用值
     * @return 如果成功设置返回true,否则返回false
     */
    public final boolean weakCompareAndSet(V expect, V update) {
        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
    }
    
    /**
     * 原子性地更新引用值,使用给定的更新函数
     * 
     * @param updateFunction 更新函数
     * @return 更新后的引用值
     */
    public final V updateAndGet(UnaryOperator<V> updateFunction) {
        V prev, next;
        do {
            prev = get();
            next = updateFunction.apply(prev);
        } while (!compareAndSet(prev, next));
        return next;
    }
    
    /**
     * 原子性地更新引用值,使用给定的更新函数,并返回旧值
     * 
     * @param updateFunction 更新函数
     * @return 更新前的引用值
     */
    public final V getAndUpdate(UnaryOperator<V> updateFunction) {
        V prev, next;
        do {
            prev = get();
            next = updateFunction.apply(prev);
        } while (!compareAndSet(prev, next));
        return prev;
    }
}

5. ABA问题及解决方案

/*
 * ABA问题演示和解决方案
 */

/**
 * ABA问题演示
 * 线程1:读取值A -> 线程2:修改为B -> 线程2:再修改回A -> 线程1:CAS成功(但中间状态已改变)
 */
public class ABADemo {
    
    // 使用AtomicInteger演示ABA问题
    private static AtomicInteger atomicInt = new AtomicInteger(10);
    
    public static void abaProblemDemo() {
        // 线程1获取值
        int value1 = atomicInt.get(); // 10
        
        // 线程2修改值
        atomicInt.compareAndSet(10, 20); // 10 -> 20
        atomicInt.compareAndSet(20, 10); // 20 -> 10
        
        // 线程1执行CAS,虽然值又变回10,但中间状态已改变
        boolean success = atomicInt.compareAndSet(10, 30); // 会成功
        System.out.println("CAS success: " + success); // true
        System.out.println("Final value: " + atomicInt.get()); // 30
    }
}

/**
 * AtomicStampedReference解决ABA问题
 * 通过版本号来解决ABA问题
 */
public class AtomicStampedReference<V> {
    
    private static class Pair<T> {
        final T reference;
        final int stamp;
        Pair(T reference, int stamp) {
            this.reference = reference;
            this.stamp = stamp;
        }
    }
    
    private volatile Pair<V> pair;
    
    /**
     * 构造方法
     * 
     * @param initialRef 初始引用值
     * @param initialStamp 初始版本号
     */
    public AtomicStampedReference(V initialRef, int initialStamp) {
        pair = new Pair<V>(initialRef, initialStamp);
    }
    
    /**
     * 获取当前引用值
     * 
     * @return 当前引用值
     */
    public V getReference() {
        return pair.reference;
    }
    
    /**
     * 获取当前版本号
     * 
     * @return 当前版本号
     */
    public int getStamp() {
        return pair.stamp;
    }
    
    /**
     * 获取引用值和版本号
     * 
     * @param stampHolder 用于存储版本号的数组
     * @return 当前引用值
     */
    public V get(int[] stampHolder) {
        Pair<V> pair = this.pair;
        stampHolder[0] = pair.stamp;
        return pair.reference;
    }
    
    /**
     * 原子性地比较并设置引用值和版本号
     * 
     * @param expectedReference 预期引用值
     * @param newReference 新引用值
     * @param expectedStamp 预期版本号
     * @param newStamp 新版本号
     * @return 如果成功设置返回true,否则返回false
     */
    public boolean compareAndSet(V expectedReference,
                                 V newReference,
                                 int expectedStamp,
                                 int newStamp) {
        Pair<V> current = pair;
        return
            expectedReference == current.reference &&
            expectedStamp == current.stamp &&
            (newReference == current.reference && newStamp == current.stamp ||
             casPair(current, new Pair<V>(newReference, newStamp)));
    }
    
    /**
     * CAS更新Pair对象
     */
    private boolean casPair(Pair<V> cmp, Pair<V> val) {
        return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
    }
    
    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
    private static final long pairOffset =
        objectFieldOffset(UNSAFE, AtomicStampedReference.class, "pair");
    
    private static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
                                          Class<?> c, String fieldName) {
        try {
            return UNSAFE.objectFieldOffset(c.getDeclaredField(fieldName));
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }
}

/**
 * 使用AtomicStampedReference解决ABA问题的示例
 */
public class ABASolutionDemo {
    
    private static AtomicStampedReference<Integer> stampedRef = 
        new AtomicStampedReference<>(10, 0);
    
    public static void solveABAProblem() {
        // 获取当前值和版本号
        int[] stampHolder = new int[1];
        Integer value1 = stampedRef.get(stampHolder);
        int stamp1 = stampHolder[0];
        
        // 线程2修改值和版本号
        stampedRef.compareAndSet(10, 20, stamp1, stamp1 + 1);
        stampedRef.compareAndSet(20, 10, stamp1 + 1, stamp1 + 2);
        
        // 线程1执行CAS,现在会失败因为版本号不匹配
        boolean success = stampedRef.compareAndSet(10, 30, stamp1, stamp1 + 3);
        System.out.println("CAS success: " + success); // false
        
        // 正确的方式:使用当前的版本号
        Integer currentValue = stampedRef.get(stampHolder);
        int currentStamp = stampHolder[0];
        success = stampedRef.compareAndSet(currentValue, 30, currentStamp, currentStamp + 1);
        System.out.println("Correct CAS success: " + success); // true
    }
}

6. 自旋锁实现示例

/**
 * 基于CAS的自旋锁实现
 */
public class SpinLock {
    
    // 使用AtomicReference存储锁的拥有者线程
    private AtomicReference<Thread> owner = new AtomicReference<>();
    
    /**
     * 获取锁
     */
    public void lock() {
        Thread current = Thread.currentThread();
        // 自旋获取锁
        while (!owner.compareAndSet(null, current)) {
            // 如果CAS失败,继续自旋
        }
    }
    
    /**
     * 释放锁
     */
    public void unlock() {
        Thread current = Thread.currentThread();
        // 释放锁
        owner.compareAndSet(current, null);
    }
}

/**
 * 改进的自旋锁,支持重入
 */
public class ReentrantSpinLock {
    
    private AtomicReference<Thread> owner = new AtomicReference<>();
    private AtomicInteger count = new AtomicInteger(0);
    
    /**
     * 获取锁
     */
    public void lock() {
        Thread current = Thread.currentThread();
        // 如果当前线程已经持有锁,增加计数
        if (owner.get() == current) {
            count.incrementAndGet();
            return;
        }
        
        // 自旋获取锁
        while (!owner.compareAndSet(null, current)) {
            // 自旋等待
        }
        count.set(1);
    }
    
    /**
     * 释放锁
     */
    public void unlock() {
        Thread current = Thread.currentThread();
        // 只有锁的拥有者才能释放锁
        if (owner.get() == current) {
            if (count.get() == 1) {
                // 最后一次释放,真正释放锁
                owner.compareAndSet(current, null);
                count.set(0);
            } else {
                // 减少重入计数
                count.decrementAndGet();
            }
        }
    }
}

7. CAS在并发容器中的应用

/**
 * 简化的无锁栈实现
 * 演示CAS在并发数据结构中的应用
 */
public class ConcurrentStack<E> {
    
    // 栈顶节点
    private AtomicReference<Node<E>> top = new AtomicReference<>();
    
    // 节点内部类
    private static class Node<E> {
        final E item;
        Node<E> next;
        
        Node(E item) {
            this.item = item;
        }
    }
    
    /**
     * 入栈操作
     * 
     * @param item 要入栈的元素
     */
    public void push(E item) {
        Node<E> newNode = new Node<>(item);
        Node<E> currentTop;
        do {
            currentTop = top.get();
            newNode.next = currentTop;
        } while (!top.compareAndSet(currentTop, newNode));
    }
    
    /**
     * 出栈操作
     * 
     * @return 栈顶元素,如果栈为空返回null
     */
    public E pop() {
        Node<E> currentTop;
        Node<E> newTop;
        do {
            currentTop = top.get();
            if (currentTop == null) {
                return null;
            }
            newTop = currentTop.next;
        } while (!top.compareAndSet(currentTop, newTop));
        return currentTop.item;
    }
    
    /**
     * 获取栈大小(近似值)
     * 
     * @return 栈中元素数量的近似值
     */
    public int size() {
        int count = 0;
        Node<E> current = top.get();
        while (current != null) {
            count++;
            current = current.next;
        }
        return count;
    }
}

/**
 * 简化的无锁队列实现
 */
public class ConcurrentQueue<E> {
    
    // 头节点和尾节点
    private AtomicReference<Node<E>> head = new AtomicReference<>();
    private AtomicReference<Node<E>> tail = new AtomicReference<>();
    
    // 节点内部类
    private static class Node<E> {
        final E item;
        AtomicReference<Node<E>> next = new AtomicReference<>();
        
        Node(E item) {
            this.item = item;
        }
    }
    
    /**
     * 构造方法
     */
    public ConcurrentQueue() {
        Node<E> dummy = new Node<>(null);
        head.set(dummy);
        tail.set(dummy);
    }
    
    /**
     * 入队操作
     * 
     * @param item 要入队的元素
     */
    public void enqueue(E item) {
        Node<E> newNode = new Node<>(item);
        Node<E> currentTail;
        Node<E> currentTailNext;
        
        while (true) {
            currentTail = tail.get();
            currentTailNext = currentTail.next.get();
            
            // 检查tail是否一致
            if (currentTail == tail.get()) {
                if (currentTailNext != null) {
                    // tail指针滞后,推进tail
                    tail.compareAndSet(currentTail, currentTailNext);
                } else {
                    // 尝试插入新节点
                    if (currentTail.next.compareAndSet(null, newNode)) {
                        // 插入成功,推进tail
                        tail.compareAndSet(currentTail, newNode);
                        return;
                    }
                }
            }
        }
    }
    
    /**
     * 出队操作
     * 
     * @return 队首元素,如果队列为空返回null
     */
    public E dequeue() {
        Node<E> currentHead;
        Node<E> currentTail;
        Node<E> currentHeadNext;
        
        while (true) {
            currentHead = head.get();
            currentTail = tail.get();
            currentHeadNext = currentHead.next.get();
            
            // 检查head是否一致
            if (currentHead == head.get()) {
                if (currentHead == currentTail) {
                    // 队列为空或只有一个元素
                    if (currentHeadNext == null) {
                        return null; // 队列为空
                    }
                    // tail指针滞后,推进tail
                    tail.compareAndSet(currentTail, currentHeadNext);
                } else {
                    // 读取值并推进head
                    E item = currentHeadNext.item;
                    if (head.compareAndSet(currentHead, currentHeadNext)) {
                        return item;
                    }
                }
            }
        }
    }
}

8. CAS性能分析和注意事项

/**
 * CAS性能测试示例
 */
public class CASTest {
    
    private static final int THREAD_COUNT = 10;
    private static final int INCREMENT_COUNT = 1000000;
    
    // 测试AtomicInteger性能
    private static AtomicInteger atomicCounter = new AtomicInteger(0);
    
    // 测试synchronized性能
    private static int syncCounter = 0;
    private static final Object lock = new Object();
    
    public static void performanceTest() throws InterruptedException {
        // 测试AtomicInteger
        long startTime = System.currentTimeMillis();
        Thread[] atomicThreads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            atomicThreads[i] = new Thread(() -> {
                for (int j = 0; j < INCREMENT_COUNT; j++) {
                    atomicCounter.incrementAndGet();
                }
            });
            atomicThreads[i].start();
        }
        
        for (Thread thread : atomicThreads) {
            thread.join();
        }
        long atomicTime = System.currentTimeMillis() - startTime;
        
        // 测试synchronized
        startTime = System.currentTimeMillis();
        Thread[] syncThreads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            syncThreads[i] = new Thread(() -> {
                for (int j = 0; j < INCREMENT_COUNT; j++) {
                    synchronized (lock) {
                        syncCounter++;
                    }
                }
            });
            syncThreads[i].start();
        }
        
        for (Thread thread : syncThreads) {
            thread.join();
        }
        long syncTime = System.currentTimeMillis() - startTime;
        
        System.out.println("AtomicInteger time: " + atomicTime + "ms");
        System.out.println("Synchronized time: " + syncTime + "ms");
        System.out.println("AtomicInteger result: " + atomicCounter.get());
        System.out.println("Synchronized result: " + syncCounter);
    }
}

/**
 * CAS使用注意事项
 */
public class CASBestPractices {
    
    /**
     * 1. 避免ABA问题
     * 使用AtomicStampedReference或AtomicMarkableReference
     */
    public void avoidABA() {
        AtomicStampedReference<Integer> stampedRef = 
            new AtomicStampedReference<>(1, 0);
        // 使用版本号避免ABA问题
    }
    
    /**
     * 2. 避免过度自旋
     * 在高竞争情况下,CAS失败率高,自旋消耗CPU
     */
    public void avoidBusySpin() {
        AtomicBoolean lock = new AtomicBoolean(false);
        
        // 不好的实现
        /*
        while (!lock.compareAndSet(false, true)) {
            // 空循环,消耗CPU
        }
        */
        
        // 好的实现
        while (!lock.compareAndSet(false, true)) {
            Thread.yield(); // 让出CPU时间片
            // 或者使用LockSupport.parkNanos(1); // 短暂阻塞
        }
    }
    
    /**
     * 3. 注意内存可见性
     * 使用volatile字段确保内存可见性
     */
    public void memoryVisibility() {
        // AtomicInteger内部使用volatile确保可见性
        AtomicInteger counter = new AtomicInteger(0);
    }
    
    /**
     * 4. 合理使用弱CAS
     * 在某些平台,weakCompareAndSet可能更高效
     */
    public void weakCAS() {
        AtomicInteger counter = new AtomicInteger(0);
        // 在某些情况下使用weakCompareAndSet
        counter.weakCompareAndSet(0, 1);
    }
    
    /**
     * 5. 注意ABA问题的实际影响
     * 不是所有场景都需要解决ABA问题
     */
    public void whenToSolveABA() {
        // 对于简单的计数器,ABA问题通常不影响结果
        AtomicInteger counter = new AtomicInteger(0);
        
        // 对于指针或引用,ABA问题可能影响正确性
        AtomicReference<Node> head = new AtomicReference<>();
    }
}

9. 核心设计要点总结

9.1 CAS算法原理

  • Compare: 比较内存位置的当前值与预期值
  • And: 如果相等则继续
  • Swap: 将内存位置的值更新为新值
  • 整个操作是原子性的

9.2 优势

  • 无锁: 不需要操作系统层面的锁机制
  • 高性能: 在低竞争情况下性能优于传统锁
  • 非阻塞: 线程不会被阻塞,减少上下文切换

9.3 劣势

  • ABA问题: 值从A变为B再变为A时可能产生问题
  • 自旋消耗: 高竞争情况下CPU消耗大
  • 只能保证一个共享变量的原子操作: 需要额外机制保证多个变量

9.4 应用场景

  • 原子计数器: AtomicInteger等
  • 无锁数据结构: 无锁栈、队列等
  • 自旋锁: 轻量级锁实现
  • 并发容器: ConcurrentHashMap等

9.5 最佳实践

  • 合理评估竞争程度选择CAS或传统锁
  • 注意ABA问题并选择合适的解决方案
  • 避免过度自旋,适当使用Thread.yield()
  • 确保共享变量使用volatile保证可见性

CAS作为现代并发编程的基础,为Java并发包提供了高性能的无锁算法实现,是理解Java并发机制的重要基础。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值