悲观锁和乐观锁
# 一、悲观锁(Pessimistic Lock)
定义:悲观锁认为并发冲突一定会发生,因此在操作数据之前就先加锁,在整个操作过程中持有锁,阻止其他线程同时修改,直到操作完成才释放锁。
核心思想:"先锁住再干活";操作系统互斥锁,涉及内核态切换。
比喻:你进公厕,先把门锁上。外面的人看到门锁着,就知道里面有人,只能排队等。等完事了打开锁,下一个人才能进去。
特点:
- 锁竞争时线程阻塞排队,上下文切换、线程挂起唤醒有开销;
- 多锁嵌套时存在死锁风险;
- 一旦拿到锁,可连续多次修改,重试成本低。
Java 实现:
synchronized关键字ReentrantLock- 数据库的
SELECT ... FOR UPDATE
# 二、乐观锁(Optimistic Lock)
定义:乐观锁认为并发冲突很少发生,因此操作时不加锁,只在最后提交更新时检查一下,在这期间有没有其他人改过数据。如果有冲突,就放弃或重试。
核心思想:"先干活,提交时再检查有没有冲突";**CAS (Compare And Swap) ** 或版本号机制。
比喻:你用共享单车扫码骑走,没人拦你。但你锁车还车时,系统会检查这段时间有没有人同时扫了这辆车,有冲突就让你重试一下。
特点:
- 全程无线程阻塞,线程一直在运行;
- 无独占锁,天然不会产生死锁;
- 校验失败就重试,高冲突下会无限自旋。
Java 实现:
AtomicInteger(CAS 机制)StampedLock数据库的 version 字段
// 乐观锁示例(数据库 version 字段) UPDATE account SET balance = balance - 100, version = version + 1 WHERE id = 1 AND version = 5; -- 期望版本还是 5 -- 如果影响行数 = 0,说明被别人改过了,重试或放弃
# CAS 算乐观锁还是悲观锁?
CAS(Compare And Swap)是 CPU 硬件层面的原子操作,通常被认为是乐观锁的实现基础。
但严格来说,CAS 本身是无锁的,既不是乐观也不是悲观。它是乐观锁的"兵器",不是"兵法"。
// 伪代码 CAS 自增
while (!compareAndSwap(oldVal, oldVal + 1)) {
// 重试,空循环
}
# AQS
AQS 本身不是锁,它既可以用来实现悲观锁(如 ReentrantLock),也可以用来实现乐观锁(如 CountDownLatch 的部分逻辑)
AQS (AbstractQueuedSynchronizer)是 Java 提供的一个用来构建锁和同步器的抽象框架。它维护了一个 volatile int state 状态变量 + 一个 FIFO 线程等待队列。
CAS 是硬件指令,AQS 是 Java 框架
上次更新: 2026-06-08 17:48:15