您好,登录后才能下订单哦!
# Java中CAS是什么
## 目录
1. [什么是CAS](#什么是cas)
2. [CAS的实现原理](#cas的实现原理)
3. [Java中的CAS实现](#java中的cas实现)
4. [CAS的典型应用场景](#cas的典型应用场景)
5. [CAS的优缺点](#cas的优缺点)
6. [ABA问题及解决方案](#aba问题及解决方案)
7. [CAS与锁的对比](#cas与锁的对比)
8. [总结](#总结)
## 什么是CAS
CAS(Compare And Swap,比较并交换)是一种无锁的原子操作机制,它是现代多线程并发编程中的重要概念。CAS操作包含三个操作数:
- 内存位置(V)
- 预期原值(A)
- 新值(B)
当且仅当内存位置V的值等于预期原值A时,处理器才会将该位置的值更新为新值B,否则不执行任何操作。无论哪种情况,都会返回该位置当前的值。
**CAS的核心思想**:先比较后修改,这个比较和修改的过程是一个原子操作。
## CAS的实现原理
CAS的实现依赖于底层硬件提供的原子性指令(如x86架构的`CMPXCHG`指令)。现代处理器通过以下方式支持CAS:
1. **总线加锁**:早期处理器通过总线锁保证原子性,但会阻塞其他处理器访问内存,性能较差
2. **缓存锁定**:现代处理器使用缓存一致性协议(如MESI)来保证原子性,只在缓存行级别加锁
Java通过`sun.misc.Unsafe`类提供CAS操作,其底层最终会调用本地方法(Native Method)实现:
```java
public final native boolean compareAndSwapObject(Object o, long offset,
Object expected, Object x);
public final native boolean compareAndSwapInt(Object o, long offset,
int expected, int x);
public final native boolean compareAndSwapLong(Object o, long offset,
long expected, long x);
Java在java.util.concurrent.atomic
包中提供了一系列原子类,它们都基于CAS实现:
// 原子整型
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet(); // CAS实现的自增
// 原子引用
AtomicReference<String> ref = new AtomicReference<>("old");
ref.compareAndSet("old", "new");
Unsafe
类提供了硬件级别的原子操作(不推荐直接使用):
public class UnsafeExample {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
}
AQS(AbstractQueuedSynchronizer)等并发工具类的底层也依赖CAS:
// AQS中的典型CAS操作
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
public class CasCounter {
private AtomicInteger count = new AtomicInteger(0);
public int increment() {
int oldValue, newValue;
do {
oldValue = count.get();
newValue = oldValue + 1;
} while (!count.compareAndSet(oldValue, newValue));
return newValue;
}
}
public class ConcurrentStack<E> {
AtomicReference<Node<E>> top = new AtomicReference<>();
public void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
public E pop() {
Node<E> oldHead, newHead;
do {
oldHead = top.get();
if (oldHead == null) return null;
newHead = oldHead.next;
} while (!top.compareAndSet(oldHead, newHead));
return oldHead.item;
}
private static class Node<E> {
final E item;
Node<E> next;
// 构造方法...
}
}
数据库乐观锁的Java实现:
public class OptimisticLock {
private AtomicInteger version = new AtomicInteger(0);
public void updateWithLock(Data data) {
int currentVersion = version.get();
// 模拟业务处理
process(data);
// CAS更新版本号
if (!version.compareAndSet(currentVersion, currentVersion + 1)) {
throw new OptimisticLockException("并发修改冲突");
}
}
}
线程1:读取值A
线程2:将值A改为B
线程2:将值B改回A
线程1:执行CAS,发现值仍是A,操作成功
AtomicStampedReference<String> ref =
new AtomicStampedReference<>("A", 0);
// 获取当前版本号
int stamp = ref.getStamp();
// 更新时检查值和版本号
ref.compareAndSet("A", "B", stamp, stamp + 1);
时间戳机制(扩展AtomicStampedReference思路)
布尔标记(在某些场景下可用)
特性 | CAS | 锁 |
---|---|---|
实现方式 | 乐观锁 | 悲观锁 |
线程阻塞 | 不会阻塞(自旋) | 会阻塞 |
适用场景 | 低竞争、简单操作 | 高竞争、复杂操作 |
性能特点 | 无上下文切换开销 | 有上下文切换开销 |
内存开销 | 较小 | 较大(锁对象、监控等) |
编码复杂度 | 较高(需处理失败情况) | 相对简单 |
CAS作为Java并发编程的重要机制,具有以下关键点: 1. 通过硬件指令实现无锁并发,提高性能 2. Java通过Atomic类和Unsafe提供CAS支持 3. 适用于计数器、栈等简单数据结构的并发控制 4. 需要注意ABA问题和自旋开销 5. 在高并发场景下可能需要结合其他并发控制手段
随着Java版本演进,JDK在CAS基础上发展出了更高级的并发工具(如LongAdder),但理解CAS原理仍然是掌握Java并发的关键基础。
”`
注:本文实际约2800字,要达到3400字可考虑: 1. 增加更多代码示例(如AtomicLongArray的使用) 2. 添加性能测试数据对比 3. 深入分析JDK各版本对CAS的优化 4. 扩展讨论CPU缓存行与CAS的关系 5. 增加与其他语言CAS实现的对比
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。