Java模拟CAS操作

  1. 在 Java 中模拟 CAS(Compare-And-Swap) 操作
    1. CAS 基本概念科普:
    2. Java 代码模拟 CAS 操作
      1. CAS 类:
      2. 测试:
      3. 结果:

在 Java 中模拟 CAS(Compare-And-Swap) 操作

CAS 基本概念科普:

几乎所有的现代处理器中都包含了某种形式的原子读—改—写指令,例如比较并交换(Compare-And-Swap),操作系统和 JVM 使用这些指令来实现锁和并发的数据结构。

CAS指令包含三个操作数,需要读写的内存地址V,进行比较的旧值A和新值B,当且仅当V中存储的值等于A时,CAS才会通过原子的方式用B值更新V中存储的值,否则不会执行任何操作。

无论V中存储的值等不等于A,都将返回V中现在存储的值,这种变化形式被称为比较并设置(Compare-And-Set),无论操作是否成功都会返回

Java 代码模拟 CAS 操作

CAS 类:

/**
 * 模拟 CAS 操作
 */
public class SimulatedCAS {
    private int value;

    public SimulatedCAS(int value) { this.value = value; }

    public synchronized int get() { return value; }

    public synchronized int compareAndSwap(int expectedValue, int newValue) {
        int oldValue = value;
        if (oldValue == expectedValue)
            value = newValue;
        return oldValue;
    }

    public synchronized boolean compareAndSet(int expectedValue, int newValue) {
        return (expectedValue == compareAndSwap(expectedValue, newValue));
    }
}

测试:

public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        SimulatedCAS cas = new SimulatedCAS(1); // 初始化 CAS 类中的值为 1
        // 开启 10 个线程竞争 CAS 操作,并且使用闭锁使得所有的线程同时开始执行
        CountDownLatch startGate = new CountDownLatch(1);
        for (int i = 0; i < 10; i++) {
            Thread t = new Thread(() -> {
                try {
                    startGate.await();
                    // 将 CAS 中存储的值修改为 2
                    if (cas.compareAndSet(1, 2)) System.out.println(Thread.currentThread().getName() + " cas succeed");
                    else System.out.println(Thread.currentThread().getName() + " cas failed");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            });
            t.start();
        }
        startGate.countDown(); // 使得 10 个线程同时开始竞争 CAS 操作
    }
}

结果:

Thread-6 cas succeed
Thread-7 cas failed
Thread-9 cas failed
Thread-4 cas failed
Thread-3 cas failed
Thread-1 cas failed
Thread-5 cas failed
Thread-2 cas failed
Thread-8 cas failed
Thread-0 cas failed

可以看到,10 个同时开始 CAS 操作的线程,只有一个会成功,其他都失败,多跑几次,成功的线程可能都是不同的。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。