锁机制实现详解 — 知识地图
本笔记为 MOC(Map of Content)
这是锁机制主题的入口。点击下方链接跳转到对应的原子笔记。
锁的分类体系
| 分类维度 | 锁类型 | 说明 |
|---|---|---|
| 按操作类型 | 读锁(共享锁) | 多个事务可同时持有,用于读取 |
| 写锁(排他锁) | 同一时间只能一个事务持有,用于写入 | |
| 按锁定范围 | 行锁 | 只锁定一行数据 |
| 表锁 | 锁定整个表 | |
| 页锁 | 锁定数据页(介于行锁和表锁之间) | |
| 按公平性 | 公平锁与非公平锁 | 公平锁按 FIFO 排队,非公平锁允许插队 |
| 按乐观程度 | 悲观锁 | 假设冲突会发生,先加锁 |
| 乐观锁 | 假设冲突少,更新时检查 |
详细笔记
| 笔记 | 简介 |
|---|---|
| 悲观锁 | 数据库悲观锁,SELECT FOR UPDATE / LOCK IN SHARE MODE |
| MySQL SELECT FOR UPDATE 锁粒度分析 | FOR UPDATE 的行锁、间隙锁、意向锁范围分析 |
| 乐观锁 | 版本号/CAS 乐观并发控制 |
| Java读写锁-ReadWriteLock | JVM 级别 ReadWriteLock,读写分离 |
| 公平锁与非公平锁 | 公平锁/非公平锁原理、AQS 实现、性能对比和选型 |
| 分布式锁实现 | Redis / Zookeeper 分布式锁实现 |
锁机制对比总结
| 锁类型 | 实现方式 | 并发性能 | 适用场景 |
|---|---|---|---|
| 悲观锁 | SELECT FOR UPDATE | 低 | 写多读少、库存扣减 |
| 乐观锁 | 版本号/CAS | 高 | 读多写少、普通更新 |
| 读写锁 | ReadWriteLock | 中高 | 缓存读写分离 |
| 分布式锁 | Redis/ZK | 中 | 跨进程/跨机器 |
| 公平锁/非公平锁 | AQS(AbstractQueuedSynchronizer) | 非公平锁高 | ReentrantLock 公平性策略选择 |
实际业务场景示例
场景1:库存扣减(悲观锁)
@Transactional
public boolean purchase(Long productId, int quantity) {
Stock stock = stockRepository.findByProductIdForUpdate(productId);
if (stock.getCount() < quantity) {
throw new BusinessException("库存不足");
}
stock.setCount(stock.getCount() - quantity);
stockRepository.save(stock);
orderService.createOrder(productId, quantity);
return true;
}场景2:用户积分更新(乐观锁)
@Transactional
public boolean updatePoints(Long userId, int points) {
int retryCount = 3;
while (retryCount > 0) {
User user = userRepository.findById(userId).orElse(null);
int currentPoints = user.getPoints();
user.setPoints(currentPoints + points);
try {
userRepository.save(user);
return true;
} catch (OptimisticLockingFailureException e) {
retryCount--;
if (retryCount == 0) {
throw new BusinessException("更新失败,请重试");
}
}
}
return false;
}