网站首页 > java教程 正文
一、什么是CAS
CAS(Compare and Swap)是处理并发问题的常用技术之一,它解决了线程安全和数据一致性问题。
CAS 是一种乐观锁机制,它是通过底层硬件提供的原子操作指令实现的,能够保证在多线程同时访问同一变量时,只有一个线程可以修改该变量的值。
CAS操作通常基于三个参数:内存位置V、期望值A和新值B。
CAS操作的执行过程如下:
1.首先,读取内存位置V的当前值,并将其与期望值A进行比较。
2.如果两者相等,则将内存位置V的值修改为新值B,并返回true,表示修改成功。
3.如果两者不相等,则不作修改,并返回false,表示修改失败。
简单来说就是:如果当前内存位置V的值等于期望值A,则将其修改为新值B;否则不做任何操作。
二、Java中的CAS
在 Java 中,CAS 操作通常是通过 sun.misc.Unsafe 类来提供支持的。Unsafe 类提供了一组底层操作,可以直接访问内存并执行一些原子性操作。如下是 Unsafe 中的三个 native 关键字修饰的CAS方法,Java 中的 CAS 操作都是通过这三个方法实现的。
public final class Unsafe {
......
// Object 的 CAS操作
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
// int 的 CAS操作
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
// long 的 CAS操作
public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
// 自旋调用 CAS操作
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
public final long getAndAddLong(Object var1, long var2, long var4) {
long var6;
do {
var6 = this.getLongVolatile(var1, var2);
// 自旋调用 CAS操作
} while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));
return var6;
}
public final int getAndSetInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
// 自旋调用 CAS操作
} while(!this.compareAndSwapInt(var1, var2, var5, var4));
return var5;
}
public final long getAndSetLong(Object var1, long var2, long var4) {
long var6;
do {
var6 = this.getLongVolatile(var1, var2);
// 自旋调用 CAS操作
} while(!this.compareAndSwapLong(var1, var2, var6, var4));
return var6;
}
public final Object getAndSetObject(Object var1, long var2, Object var4) {
Object var5;
do {
var5 = this.getObjectVolatile(var1, var2);
// 自旋调用 CAS操作
} while(!this.compareAndSwapObject(var1, var2, var5, var4));
return var5;
}
......
}
例如 AtomicInteger 源码中使用 CAS 的部分源码附带说明如下:
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// 使用 Unsafe.compareAndSwapInt 来更新值
private static final Unsafe unsafe = Unsafe.getUnsafe();
// 获取 value 属性在对象中的偏移量
private static final long valueOffset;
static {
try {
// 获取 value 属性在对象中的偏移量
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
}
// 使用 volatile 修饰 value 属性,保证线程之间的可见性
private volatile int value;
......
// 自增并返回自增前的值
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
// 自增并返回自增后的值
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
......
}
三、注意事项
需要注意的是,虽然CAS操作具有很好的互斥性和原子性,但也存在一些需要注意的问题:
- 自旋次数过多会影响性能:当多个线程访问同一变量时,如果修改失败,CAS操作会进行自旋等待,以期望其他线程修改完成后再次尝试。如果自旋次数过多,会浪费大量的CPU资源。
- 受限于底层硬件平台:由于CAS操作是基于底层硬件平台提供的支持,因此受限于硬件平台的类型和性能,不同的硬件平台可能对CAS操作的具体实现略有差别。
- 无法避免ABA问题:当变量从A -> B -> A后,如果期望值A没有变化,CAS操作仍然会成功,但实际上变量的值已经发生了变化。如果你想了解更多关于ABA问题,请查看我的另一篇文章【 还不知道ABA问题?大厂面试Java必提的问题 】
猜你喜欢
- 2025-07-19 Java AtomicInteger操作详解(java attachment)
- 2025-07-19 无锁同步-JAVA之Volatile、Atomic和CAS
- 2025-07-19 Java 作用域详解:从变量可见性到代码封装
- 2025-07-19 CompletableFuture源码分析(fragment源码分析)
- 2025-07-19 Java并发编程从入门到进阶 多场景实战
- 2025-07-19 一文搞懂 CAS 操作与 ABA 问题:高并发编程的关键知识点
- 2025-07-19 Java 内存模型、JVM 内存结构(java的内存模型)
- 2025-07-19 Java面试必备八股文(java面试必备八股文河北人社)
- 2025-07-19 java VarHandle介绍(java variant)
- 2025-07-19 【多线程】Java多线程与并发编程全解析
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)