在 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 操作的线程,只有一个会成功,其他都失败,多跑几次,成功的线程可能都是不同的。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。