在Java中,CAS(Compare-and-Swap)是一种无锁算法,通过JNI(Java Native Interface)调用本地方法来利用处理器提供的原子指令实现。它可以保证在多线程环境下的原子性和可见性,而无需使用传统的锁机制。以下是一个简单的Java示例,通过java.util.concurrent.atomic
包下的AtomicInteger
类来演示CAS的原理:
import java.util.concurrent.atomic.AtomicInteger;
public class CASExample {
public static AtomicInteger atomicInteger = new AtomicInteger(0);
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
// 使用CAS尝试将原子整数增加1
while (true) {
// 获取当前值
int currentValue = atomicInteger.get();
// 计算新的期望值
int newValue = currentValue + 1;
// 使用compareAndSet方法尝试原子地更新值
if (atomicInteger.compareAndSet(currentValue, newValue)) {
// 更新成功,退出循环
break;
} else {
// 更新失败,当前值已被其他线程改变,继续循环尝试
}
}
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
// 同理,第二个线程也在尝试增加原子整数
while (true) {
int currentValue = atomicInteger.get();
int newValue = currentValue + 1;
if (atomicInteger.compareAndSet(currentValue, newValue)) {
break;
}
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 最终打印的结果将是20000,表明两个线程的操作是互斥且原子完成的
System.out.println("Final Value: " + atomicInteger.get());
}
}
上述代码中,我们创建了两个线程t1
和t2
,每个线程都在尝试递增一个共享的AtomicInteger
实例。compareAndSet
方法接受两个参数:当前预期的值和新的值。这个方法尝试将原子整数的值从预期的当前值更新为新值,如果当前原子整数的实际值与预期值相匹配,则更新,并返回true
;如果不匹配,则不执行更新操作并返回false
。这意味着即使在高并发环境下,多个线程同时尝试更新同一变量时,只有一个线程能成功完成更新,其余线程将继续循环尝试直至成功,从而确保了在无锁的情况下也能实现并发控制和数据一致性。