锁机制实现详解 — 知识地图

本笔记为 MOC(Map of Content)

这是锁机制主题的入口。点击下方链接跳转到对应的原子笔记。

锁的分类体系

分类维度锁类型说明
按操作类型读锁(共享锁)多个事务可同时持有,用于读取
写锁(排他锁)同一时间只能一个事务持有,用于写入
按锁定范围行锁只锁定一行数据
表锁锁定整个表
页锁锁定数据页(介于行锁和表锁之间)
按公平性公平锁与非公平锁公平锁按 FIFO 排队,非公平锁允许插队
按乐观程度悲观锁假设冲突会发生,先加锁
乐观锁假设冲突少,更新时检查

详细笔记

笔记简介
悲观锁数据库悲观锁,SELECT FOR UPDATE / LOCK IN SHARE MODE
MySQL SELECT FOR UPDATE 锁粒度分析FOR UPDATE 的行锁、间隙锁、意向锁范围分析
乐观锁版本号/CAS 乐观并发控制
Java读写锁-ReadWriteLockJVM 级别 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;
}

参考链接