reentrantlock默认为非公平锁,启用公平锁需构造时传入true,但会降低吞吐量20%–40%,仅适用于存在线程饥饿风险或响应时间敏感的场景。

ReentrantLock 默认是非公平锁,要实现公平锁只需在构造时传入 true 参数,但“公平”不等于“高性能”,反而常带来吞吐量下降。性能调优的关键不是盲目开启公平模式,而是根据实际竞争场景权衡公平性与吞吐效率。
公平锁的创建方式很简单,但代价需提前评估
公平锁通过排队机制(FIFO)保证等待时间最长的线程优先获取锁,避免线程饥饿,但会牺牲 CPU 缓存友好性和上下文切换效率。
- 构造方式:
new ReentrantLock(true) - 非公平锁(默认):允许新线程“插队”,在低竞争时命中率高,吞吐更强
- 公平锁:每次加锁都需检查同步队列头节点,增加 volatile 读和 CAS 开销
- 实测表明,在中高并发、短临界区场景下,公平锁吞吐量可能比非公平锁低 20%–40%
只在真正需要公平性的场景启用公平锁
公平锁适合对响应时间敏感、或存在明显长耗时操作导致线程饥饿风险的场景,而非所有并发控制场景。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 适用情况:任务执行时间差异大(如混合 IO 和计算)、调度逻辑依赖获取顺序、测试环境需稳定复现竞态
- 不适用情况:高频短操作(如计数器累加)、线程数远小于核心数、锁持有时间极短(
- 可先用
ThreadMXBean或 JFR 观察java.util.concurrent.locks.AbstractQueuedSynchronizer$Node队列长度和平均等待时间,再决定是否启用公平模式
配合其他手段缓解公平锁性能瓶颈
即使启用公平锁,也可通过减少锁粒度、避免锁内阻塞、合理使用 tryLock 等方式提升整体效率。
- 缩小临界区:只对真正共享且需互斥的代码加锁,避免在锁内做日志、网络调用等耗时操作
- 考虑分段锁或读写锁替代:如用
StampedLock替代纯写场景,或按 key 分片使用多个 ReentrantLock - 慎用
lockInterruptibly()和tryLock(long, TimeUnit):公平锁下超时等待仍需排队,可能延长等待链 - 监控
getQueueLength()和hasQueuedThreads(),持续观察是否出现长队列堆积,及时优化业务逻辑
用 JMH 做真实场景压测,别依赖理论结论
公平锁的实际开销高度依赖 JVM 版本、CPU 架构、GC 策略和具体 workload,必须结合业务流量模型验证。
- 编写 JMH 测试时,模拟真实线程数、锁持有时间分布(如 80% 短操作 + 20% 长操作)
- 对比指标:吞吐量(ops/ms)、平均延迟、99% 延迟、GC 次数、CPU cache miss 率(可用 perf 工具)
- 注意预热轮次足够(如 10 轮 warmup),避免 JIT 未优化导致数据失真
公平锁是工具,不是银弹。它解决的是调度策略问题,不是性能问题。真正有效的调优,是从业务语义出发判断是否需要公平,再用数据驱动决策,而不是把“公平”当作默认选项。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










