synchronized固定为非公平锁,其非公平性体现在锁释放时新线程可直接抢占空闲锁,无需等待队列中线程优先获取,且jvm未实现fifo唤醒机制;而reentrantlock可通过构造参数显式选择公平或非公平策略。

synchronized 是 Java 中最基础的内置锁机制,它只支持非公平锁,且无法配置为公平锁。这种非公平性不是设计缺陷,而是 JVM 在实现层面做出的性能权衡。
synchronized 的非公平性体现在哪里
synchronized 的非公平性主要表现在:当锁被释放时,不保证唤醒等待队列中排在最前面的线程;新到来的线程可以和刚被唤醒的线程“竞争”获取锁,甚至可能“插队”成功。
- JVM 底层通过
monitorenter/monitorexit指令操作对象监视器(Monitor)。 - Monitor 内部维护一个
_EntryList(等待队列)和一个_Owner(当前持有锁的线程)。 - 但 JVM 并未强制要求“先入队、先唤醒”,而是允许新请求锁的线程直接尝试抢占——只要此时锁空闲,它就能立刻获得,哪怕
_EntryList里已有等待线程。 - 这就是典型的“非公平”行为:后到的线程可能比早到的线程更早拿到锁。
为什么 synchronized 不能是公平锁
-
synchronized的实现由 JVM 直接托管,不基于 AQS(AbstractQueuedSynchronizer),而公平性逻辑(如检查队列头、FIFO 调度)必须依赖 AQS 的排队机制。 - ReentrantLock 的公平锁靠
FairSync子类 +hasQueuedPredecessors()方法实现排队校验;synchronized没有这类可扩展的调度逻辑。 - JVM 规范未定义公平性语义,各厂商(HotSpot)默认采用非公平策略以减少上下文切换和提升吞吐量。
和 ReentrantLock 的对比更清晰
-
ReentrantLock lock = new ReentrantLock(true)→ 显式公平锁,严格 FIFO。 -
ReentrantLock lock = new ReentrantLock()或new ReentrantLock(false)→ 非公平锁,行为与synchronized类似。 -
synchronized(obj) { ... }→ 唯一选择,且固定为非公平。
实际影响有哪些
- ✅ 优势:减少线程挂起/唤醒开销,高并发下吞吐更高。
- ❌ 风险:存在线程饥饿可能(尤其在持续高争抢场景下,某些线程可能长期得不到执行机会)。
- ⚠️ 注意:这种“不公平”通常不影响正确性,因为 Java 内存模型仍保证了可见性与原子性;只是调度顺序不可预测。
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











