你问的三个概念——乐观锁(Optimistic Lock)、悲观锁(Pessimistic Lock)和CAS(Compare And Swap/Set)——都是并发控制和线程安全的核心机制,我给你系统地梳理一下,并且用例子和类比说明。
1️⃣ 悲观锁(Pessimistic Lock)
概念:悲观锁假设别人会同时修改你要操作的数据,所以在你操作数据之前,就先上锁,确保别人不能改,直到你完成操作后再释放锁。
特点:
- 保证数据安全,几乎不会出现冲突。
- 代价是性能低,因为锁住期间其他线程必须等待。
- 常见实现:
synchronized
(Java)、ReentrantLock
、数据库中的行锁/表锁。
类比:你去图书馆借书,悲观锁就像你把书拿到手上,并锁在你的抽屉里,别人必须等你还书才能借。
Java 示例:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
这里的 synchronized
就是悲观锁。
2️⃣ 乐观锁(Optimistic Lock)
概念:乐观锁假设别人不会同时修改你要操作的数据,在修改时检查一下数据是否被修改过,如果被修改过,则重试。
特点:
- 不加锁,性能好,适合读多写少的场景。
- 实现依赖于版本号或者时间戳。
- 如果冲突发生,需要回退或者重试。
类比:你去图书馆借书,乐观锁就像你先拿书去借阅区看,拿去结账时发现别人已经借走了,你就重新选择其他书。
Java 示例(版本号实现):
class OptimisticCounter {
private int count = 0;
private int version = 0;
public boolean increment() {
int oldVersion = version;
int oldCount = count;
// 先假设没人修改
int newCount = oldCount + 1;
// 检查版本号
if (oldVersion == version) {
count = newCount;
version++;
return true;
} else {
return false; // 冲突,需要重试
}
}
}
3️⃣ CAS(Compare-And-Swap / Compare-And-Set)
概念:CAS 是一种原子操作,它的机制是:
比较内存中的值是否等于期望值,如果相等则更新为新值,否则不更新。
它是乐观锁的硬件级实现。
特点:
- 无锁操作,提高性能。
- 有 ABA 问题,需要额外手段处理(如版本号)。
- JVM 的
AtomicInteger
就是用 CAS 实现的。
类比:你在ATM机上存钱:
- 你看到账户余额是 100。
- 你想存 10。
- 机器检查余额还是 100,如果是,就存 10;如果别人已经改成 110,就不操作,重试。
Java 示例(AtomicInteger):
import java.util.concurrent.atomic.AtomicInteger;
class CASCounter {
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
int oldValue;
int newValue;
do {
oldValue = count.get();
newValue = oldValue + 1;
} while (!count.compareAndSet(oldValue, newValue));
}
public int getCount() {
return count.get();
}
}
这里 compareAndSet
就是 CAS 操作。
🔹 总结对比
特性 | 悲观锁 | 乐观锁 | CAS |
---|---|---|---|
锁类型 | 阻塞锁 | 无锁或版本号 | 原子操作 |
性能 | 较低 | 高 | 高 |
冲突处理 | 阻塞等待 | 检测失败重试 | 检测失败重试 |
适用场景 | 写多且冲突大 | 读多写少 | 高并发无锁场景 |
如果你愿意,我可以帮你画一张悲观锁 vs 乐观锁 vs CAS 的直观流程图,让你一眼就理解它们的差别。
你希望我画吗?
Top comments (0)