ReentrantLock虽非设计模式,但可与模板方法、策略、装饰器、享元等模式协同提升并发质量:前者封装加锁逻辑,后者分别实现策略切换、能力增强与锁实例复用。

ReentrantLock 本身不是设计模式,但和多种设计模式配合使用,能显著提升并发代码的可维护性、可扩展性和线程安全性。关键不在于“套用模式”,而是在解决具体并发问题时,自然引入合适的设计思想。
用模板方法模式封装加锁/解锁逻辑
手动写 lock() 和 unlock() 容易遗漏(尤其异常路径),模板方法能统一管控生命周期。
- 定义抽象基类,声明
doInLock()模板方法,在executeWithLock()中完成加锁 → 执行 → 解锁(finally 保证) - 子类只关注业务逻辑,不接触锁细节;锁类型(公平/非公平)、超时策略等可在基类或构造参数中配置
- 例如:库存扣减服务继承该模板,
doInLock()里只写“检查余额→扣减→记录日志”,无锁操作痕迹
用策略模式动态切换锁行为
不同场景对锁的诉求不同(如强一致性 vs 高吞吐),策略模式让锁策略可插拔。
- 定义
LockStrategy接口,实现类如BlockingLockStrategy(常规 lock)、TryLockStrategy(带超时 tryLock)、ReadLockStrategy(读写锁的读锁) - 业务类持有一个策略对象,运行时根据请求类型(如“管理员操作”走阻塞锁,“查询请求”走乐观重试)注入不同策略
- 避免硬编码
if (type == ADMIN) lock() else tryLock(1, SECONDS),便于测试和灰度
用装饰器模式增强锁能力
在不修改原有锁逻辑的前提下,叠加监控、重入检测、死锁预警等横切关注点。
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
立即学习“Java免费学习笔记(深入)”;
- 写一个
MonitoringReentrantLock,内部包裹真实 ReentrantLock,所有方法委托调用,但在lock()前打点计时、记录线程ID,在unlock()后上报耗时 - 再写一个
DeadlockDetectingLock,利用ThreadMXBean.findDeadlockedThreads()在获取锁前做轻量检测(适合开发环境) - 多个装饰器可自由组合:
new DeadlockDetectingLock(new MonitoringReentrantLock(new ReentrantLock()))
用享元模式复用锁实例,避免锁爆炸
高频小粒度资源(如用户 ID、订单号)若为每个值创建独立锁,易引发内存与竞争问题;享元集中管理有限锁实例。
- 构建
LockPool,内部用固定大小的ConcurrentHashMap+ 数组/轮询算法,将任意 key 映射到少量预分配的ReentrantLock实例上 - 映射需满足:相同 key 总命中同一把锁(一致性),不同 key 尽量分散(降低冲突)——常用
key.hashCode() & (size - 1) - 适用于“按用户ID加锁”场景,锁实例数控制在 64 或 256,而非百万级用户对应百万把锁
不复杂但容易忽略:所有模式都建立在正确使用 ReentrantLock 的基础上——始终在 finally 块 unlock、避免锁嵌套失控、优先考虑无锁方案(如 CAS、队列)。模式是手段,清晰表达并发意图才是高质量代码的核心。

















