CAS(Compare And Swap)操作是一种并发编程中的核心原子操作,它用于解决并发环境下的同步问题。CAS操作的实现原理是基于硬件指令的特性,利用“比较和交换”的方式进行。简单来说,当需要修改共享变量时,CAS先比较当前值与期望值是否相等,相等则将新值写入共享变量中,不相等则说明共享变量已被其他线程修改,当前线程需要重新尝试。
实现CAS操作需要以下三个参数:
- 要修改的共享变量内存地址V
- 预期的值A
- 新的值B
具体实现步骤如下:
- 获取当前共享变量的值V1;
- 比较V1和预期的值A,如果不相等,则说明共享变量已被其他线程修改,需要重新读取共享变量的值,继续执行步骤1;
- 如果V1和A相等,则将新的值B写入共享变量;
- 如果写入成功,则CAS操作返回true,否则CAS操作返回false。
示例1:CAS操作实现多线程安全计数器
下面是一个简单的例子,演示如何使用CAS操作实现一个多线程安全的计数器:
public class CASCounter {
private AtomicInteger count = new AtomicInteger(0);
public int getCount() {
return count.get();
}
public void increment() {
int current;
do {
current = count.get();
} while (!count.compareAndSet(current, current + 1));
}
}
在CASCounter类中,count变量被声明为一个AtomicInteger类型的对象,它提供了CAS操作的封装实现。increment()方法就是对count变量进行加1操作,其中使用了do-while循环来确保CAS操作的成功执行。如果CAS操作失败,则会一直重试,直到成功为止。
示例2:CAS操作实现乐观锁
下面是另一个例子,演示如何使用CAS操作实现乐观锁:
public class OptimisticLock {
private AtomicInteger version = new AtomicInteger(0);
private String data = "Hello, world!";
public void updateData(String newData) {
int current = version.get();
while (!version.compareAndSet(current, current + 1)) {
current = version.get();
}
data = newData;
}
public String getData() {
return data;
}
}
在OptimisticLock类中,version变量为一个AtomicInteger类型的对象,它实现了版本号的自动递增,用来判断数据是否被修改。updateData()方法就是对data变量进行更新操作,使用了CAS操作,并且在CAS操作失败时使用了循环重试的方式。getData()方法则是获取更新后的数据。
以上是CAS操作的实现原理及两个示例说明,CAS操作在Java中有广泛的应用,例如ConcurrentHashMap、AtomicInteger等类库中都使用了CAS操作实现线程安全。同时,CAS操作也是现代CPU架构提供的原子指令之一,它为高并发场景下的编程提供了强大的支持。