CAS算法
1. CAS简介
CAS叫做CompareAndSwap,比较并交换,主要是通过处理器的指令来保证操作的原子性。
CAS基本概念
- 内存位置 (V):需要进行CAS操作的内存地址。
- 预期原值 (A):期望该内存位置上的旧值。
- 新值 (B):如果旧值与预期原值相匹配,则用这个新值替换旧值。
CAS操作流程
- 比较: CAS首先读取内存位置V的当前值。
- 检查: 检查当前值是否与预期值A相等。
- 如果相等,则进行下一步。
- 如果不相等,则CAS操作失败,返回当前值或false。
- 交换: 如果当前值与预期值相等,则用新值B替换当前值。
- 返回结果: 成功后返回true,表示值已更新;或者返回false,表示值未更改
补充1:CAS操作是原子的,这意味着它要么完全执行成功,要么完全不执行。这意味着在CAS操作过程中,其他线程不能干扰这个操作。在硬件级别,这是通过CPU的特殊指令实现的,比如在Intel x86架构中使用的CMPXCHG(compare and exchange)指令。(来自网络)
补充2:在Java中,CAS操作是通过Unsafe类提供的本机方法实现的,这些方法允许直接访问底层内存。(来自网络)
2. CAS具体实践
Java中的java.util.concurrent.atomic包提供了基于CAS的原子类,如AtomicInteger、AtomicReference等。
下面结合我的所学,简单的试验一下AtmoicInteger
说明:下面用到的线程池Executors、AtmoicInteger等都是java.util.concurrent下面的类
public class TestCAS {
private static final AtomicInteger count1 = new AtomicInteger(0);
private static Integer count2 = 0;
public static void main(String[] args) throws InterruptedException, ExecutionException {
useAtomicInteger();
notUseAtomicInteger();
}
// 使用AtomicInteger
public static void useAtomicInteger() {
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 1000; i++) {
executor.submit(() -> count1.incrementAndGet());
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Use AtomicInteger Final Result count: " + count1.get());
}
// 不使用AtomicInteger
public static void notUseAtomicInteger() {
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 1000; i++) {
executor.submit(() -> count2++);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Not Use AtomicInteger Final Result count: " + count2);
}
}
结果:
结果说明:
- 使用AtomicInteger的结果因为AtomicInteger实现了CAS算法,所以结果始终是1000;
- 而没有使用AtomicInteger的结果,因为线程池异步的原因,导致每次计算的结果都会略有偏差。