synchronized默认采用非公平锁机制,因其底层Monitor实现不检查等待队列头部、不保证先来先服务,新线程可直接抢占刚释放的锁,且无公平性配置选项。

synchronized 是 Java 内置的隐式锁,它默认采用非公平锁机制——不是因为它“故意偏心”,而是由其底层实现方式决定的:线程在释放锁后,新来的线程可以立即尝试抢占,无需排队,也不检查等待队列中是否有更早请求的线程。
为什么 synchronized 不排队?
当一个线程刚释放 synchronized 锁(执行 monitorexit),JVM 并不会强制唤醒等待队列头部的线程;相反,任何此刻刚好执行到 monitorenter 的线程,只要锁空闲,就能直接获取。这相当于允许“插队”——哪怕队列里已有多个线程在等,新线程仍可能抢到锁。
- 不维护公平性逻辑:synchronized 没有像 ReentrantLock.FairSync 那样基于 AQS 的 FIFO 等待队列检查机制
- 无“先来先服务”判断:获取锁前不查询当前同步队列是否为空、也不验证自己是不是队首
- 依赖系统调度:谁抢到 CPU 时间片、谁先执行到加锁指令,谁就更可能拿到锁
和 ReentrantLock 非公平锁的区别在哪?
虽然两者都非公平,但实现路径不同:
- synchronized 的非公平是“原生级”的:由 JVM 的 Monitor 和 ObjectMonitor 直接实现,没有用户可干预的公平策略开关
- ReentrantLock 的非公平锁(NonfairSync)是显式设计的:它在 tryAcquire 中先 CAS 抢锁,失败才入队;而 synchronized 根本不提供“入队前先抢”的抽象层,它的“抢”就是唯一入口
- 你无法把 synchronized 变成公平锁——没有 fair 参数,也没有 setFairness() 方法
非公平带来的实际影响
在高并发短临界区场景下,这种机制减少了线程挂起/唤醒开销,提升了吞吐量;但代价是可能让某些线程反复抢锁失败,陷入长等待。
立即学习“Java免费学习笔记(深入)”;
- 例如:10 个线程争抢一个 synchronized 块,其中 1 个线程持续快速进出,其余 9 个可能因调度或竞争始终轮不上
- 这不是 bug,是权衡:JVM 选择以性能优先,默认放弃顺序保证
- 若业务强依赖执行顺序(如日志写入需严格保序),不应依赖 synchronized 的执行次序,而应配合队列或显式公平锁控制
怎么确认它确实是非公平的?
没有公开 API 能“读取”synchronized 的公平性,但可通过行为验证:
- 写一个测试:多个线程循环争抢同一把锁,记录各自获得锁的顺序与请求顺序——大概率出现后请求者先执行
- 对比 ReentrantLock(true):同样测试下,请求顺序与执行顺序高度一致;而 synchronized 版本明显紊乱
- 查看 OpenJDK 源码中的 ObjectMonitor::EnterI 实现,其逻辑不含队首校验,只做快速尝试和阻塞路径


















