reentrantlock 通过细粒度加锁、分片锁、超时机制等提升并发性能。只锁共享变量操作,避免锁内耗时任务;用 try-finally 确保 unlock;按资源分片减少热点;优先用 longadder 和 concurrenthashmap;合理选用 trylock 或 lockinterruptibly。

ReentrantLock 本身不直接“减少”资源竞争,而是帮你更精准地控制竞争发生的范围和方式。关键不是换锁,而是用它把原本粗放的同步收缩到真正需要保护的那几行代码,让不相关的线程不再互相阻塞。
只锁共享状态修改部分,不锁业务逻辑
很多性能问题来自把整个方法或一段包含 I/O、计算、远程调用的流程包进锁里。ReentrantLock 的价值在于能把它拆开——只在真正读写共享变量时加锁。
- 比如库存扣减,查库存可以无锁,只有
stock--这一行才需要锁 - 缓存更新和 DB 写入通常不必串行:DB 操作加锁,缓存刷新可异步或无锁完成
- 避免在
lock()和unlock()之间做日志拼接、JSON 序列化等可能慢的操作
用 try-finally 确保 unlock 执行,防止死锁
显式锁必须配对释放,否则一个线程卡住就等于整条链路堵死。synchronized 是 JVM 自动保证的,而 ReentrantLock 需要你手动兜底。
- 永远把
unlock()放在finally块里,哪怕中间抛异常也不漏掉 - 不要依赖作用域自动清理,Java 不支持析构函数
- 别在锁内调用可能抛出 unchecked exception 的复杂方法,除非你确定能捕获并正确处理
按资源分片,避免单点锁瓶颈
一个锁保护所有商品、所有用户、所有缓存项,本质上就是人为制造热点。ReentrantLock 支持多个实例,这是细粒度控制的基础。
- 对不同商品 ID 取模,分配到不同 Lock 实例上(如
locks[productId % N]) - Map 分段场景可用
ConcurrentHashMap替代自己封装,它的桶级锁已实现类似效果 - 计数类场景优先用
LongAdder,它内部用 cell 数组分散 CAS 冲突,比单个锁或 AtomicLong 更稳
配合超时与非阻塞尝试,避免线程无限等待
当锁竞争激烈时,与其让线程一直 BLOCKED,不如让它先退一步,稍后再试,或走降级路径。
- 用
tryLock(100, TimeUnit.MILLISECONDS)设定等待上限,超时后可重试、返回默认值或记录告警 - 非公平模式(默认)吞吐更高,适合大多数场景;公平模式仅在确认存在线程饥饿时启用
- 若需中断等待中的线程,用
lockInterruptibly(),配合Thread.interrupt()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











