← 返回首页

CAS算法:无锁并发的基石

📂 java ⏱ 2 min 280 words

CAS算法:无锁并发的基石

概述

CAS(Compare And Swap)是一种无锁的并发算法,它通过比较并交换的方式实现原子操作,是Java并发包的基础。

1. CAS原理

import java.util.concurrent.atomic.AtomicInteger;

public class CASDemo {
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        count.incrementAndGet();
    }

    public int getCount() {
        return count.get();
    }

    public static void main(String[] args) throws InterruptedException {
        CASDemo demo = new CASDemo();
        Thread[] threads = new Thread[10];

        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    demo.increment();
                }
            });
            threads[i].start();
        }

        for (Thread t : threads) {
            t.join();
        }

        System.out.println("Count: " + demo.getCount());
    }
}

2. 原子变量类

import java.util.concurrent.atomic.*;

public class AtomicVariableDemo {
    private AtomicInteger intCount = new AtomicInteger(0);
    private AtomicLong longCount = new AtomicLong(0L);
    private AtomicReference<User> userRef = new AtomicReference<>();
    private AtomicStampedReference<Integer> stampedRef = new AtomicStampedReference<>(0, 0);

    public void demo() {
        intCount.incrementAndGet();
        intCount.compareAndSet(10, 20);

        longCount.addAndGet(100L);

        userRef.set(new User("John"));
        userRef.compareAndSet(new User("John"), new User("Jane"));
    }
}

3. ABA问题

// ABA问题:值从A变为B,再变回A,CAS会认为没有变化
// 解决:使用AtomicStampedReference

public class ABAProblemDemo {
    private AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(0, 0);

    public void solveABA() {
        int stamp = ref.getStamp();
        Integer value = ref.getReference();
        ref.compareAndSet(value, value + 1, stamp, stamp + 1);
    }
}

4. Unsafe类

import sun.misc.Unsafe;
import java.lang.reflect.Field;

public class UnsafeDemo {
    private static Unsafe unsafe;

    static {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            unsafe = (Unsafe) field.get(null);
        } catch (Exception e) { e.printStackTrace(); }
    }

    public static void main(String[] args) {
        int[] value = {0};
        unsafe.compareAndSwapInt(value, 0, 0, 1);
        System.out.println(value[0]);
    }
}

5. LongAdder

import java.util.concurrent.atomic.LongAdder;

public class LongAdderDemo {
    private LongAdder adder = new LongAdder();

    public void increment() {
        adder.increment();
    }

    public long getCount() {
        return adder.sum();
    }
}

最佳实践

  1. 使用Atomic*类:简单原子操作优先使用
  2. 解决ABA问题:使用AtomicStampedReference
  3. 高并发场景:使用LongAdder替代AtomicLong
  4. 理解CAS原理:有助于理解并发包的实现
  5. 避免CAS循环:设置重试次数限制

总结

CAS是Java并发包的基础算法,它通过无锁的方式实现原子操作,提高了并发性能。掌握CAS原理和原子变量的使用,是理解Java并发编程的重要基础。