reentrantlock 不直接降低 cpu 开销,但通过精细控制锁范围、使用 trylock 避免阻塞、避免公平锁滥用及配合无锁结构,可显著减少线程挂起、上下文切换和自旋等待等 cpu 消耗。

ReentrantLock 本身不直接降低 CPU 开销,但它提供了精细控制锁行为的能力,从而间接大幅减少因锁竞争引发的线程挂起/唤醒、自旋等待和上下文切换等 CPU 消耗。关键不在“用不用 ReentrantLock”,而在于怎么用——核心是让锁更短、更专、更可控。
只锁真正需要保护的代码段
锁范围越宽,线程排队越久,CPU 花在等待和调度上的时间越多。ReentrantLock 支持显式界定临界区,避免把 I/O、计算、远程调用等非共享操作包进锁里。
- 错误做法:在 lock() 后立刻调用 HTTP 接口或解析大 JSON —— 线程持锁阻塞,其他线程空转或频繁挂起
- 正确做法:先完成耗时操作,再用 try-finally 仅包裹 sharedResource++ 或 map.put() 这类原子状态变更
- 示例:缓存更新 + DB 写入场景中,只对本地缓存 map 的写操作加锁,DB 操作异步或无锁执行
用 tryLock 避免无限自旋或挂起
默认 lock() 会阻塞直到获取锁,高竞争下可能触发长时间自旋(消耗 CPU)或线程挂起(增加调度开销)。tryLock 提供超时与非阻塞选项,让线程有机会退避或改走备选路径。
- lock.tryLock(100, TimeUnit.MILLISECONDS) 可防止线程在锁队列里死等
- 配合指数退避重试,比盲目重试更节省 CPU
- 对低优先级或可降级任务(如日志聚合、监控上报),获取不到锁就跳过,避免拖慢主线程
选用合适锁策略,避免公平锁滥用
ReentrantLock 默认是非公平模式,允许插队,吞吐更高;公平锁虽保证顺序,但强制排队会显著增加线程调度次数和上下文切换频率,CPU 开销反而上升。
- 除非业务逻辑明确要求“先来先服务”(如资源配额分配),否则不要 new ReentrantLock(true)
- 公平锁在高并发下会导致更多线程进入 WAITING 状态,JVM 需频繁介入调度,加重 CPU 负担
- 可通过 JFR 或 jstack 观察 BLOCKED 线程数,若持续高位,优先检查是否误用了公平锁
配合无锁结构,从源头减少锁需求
ReentrantLock 是“有锁方案里的优化”,但最优解往往是“不用锁”。它常作为过渡手段,帮你识别哪些状态真需互斥,进而替换成更轻量的并发原语。
- 计数器优先用 LongAdder,而非 lock + int++ —— 它用分片 cell 减少 CAS 冲突,CPU 缓存行争用更低
- Map 查写优先用 ConcurrentHashMap.computeIfAbsent(),它内部已做桶级同步,无需外层 lock
- 状态标记用 AtomicInteger.compareAndSet(),比加锁 setFlag(true) 更快,且无调度开销
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











