synchronized的底层原理是什么?
应先讲监视器互斥和 happens-before,再把 JVM 优化当作版本相关实现,避免背诵过时锁升级路径。
直接结论
synchronized 是 Java 语言级的监视器同步机制。实例同步方法锁定接收者对象,静态同步方法锁定对应 Class 对象,同步代码块锁定表达式得到的非空引用。进入同一监视器的线程互斥,正常或异常退出都会释放监视器;一次解锁 happens-before 后续对同一监视器的加锁,因此它同时提供互斥和内存可见性。字节码层通常体现为 monitorenter/monitorexit 或方法访问标志,但具体锁优化属于 JVM 实现。
原理与步骤
监视器是可重入的,同一线程再次进入不会自我阻塞,但必须匹配退出次数。编译器要保证异常路径也执行 monitorexit。等待通知使用 Object.wait/notify/notifyAll,并要求线程持有该对象监视器;wait 会释放监视器,唤醒后还要重新竞争并循环检查条件。ReentrantLock 同样提供可重入互斥和内存同步语义,但额外提供可中断获取、超时尝试、公平策略以及多个 Condition,代价是必须显式在 finally 中 unlock。
工程场景
简单、作用域清晰且无需超时或多个等待队列的临界区,优先 synchronized,结构化语法更不易漏释放。需要 tryLock、lockInterruptibly、公平排队或多个条件队列时,再考虑 ReentrantLock。锁内只保护共享状态不变量,不执行慢网络调用;多个锁必须约定顺序以避免死锁。对只读多写少结构也要先评估不可变快照、并发集合或读写锁是否更合适,不能把所有线程安全问题都转成粗粒度对象锁。
验证与边界
验证应围绕可观察语义:并发递增结果、异常退出后其他线程能否进入、重入以及 happens-before 可见性,而不是依赖对象头位模式。偏向锁、轻量级锁、锁消除等说法会随 JVM 和版本演进,面试中必须标成实现优化而非 JLS 承诺。synchronized 不支持获取锁时的超时和显式中断;线程在进入前阻塞时的响应方式也与 Lock API 不同。选择依据应是语义需求和测量结果,而非“内置锁一定慢”的旧结论。
答题练习
- 1监视器互斥与可重入
- 2解锁到后续加锁的 happens-before
- 3语言契约与 JVM 优化分层
常见错误
- 背诵某一版 JVM 的固定锁升级路线
- 忘记 wait 必须循环检查条件
可能追问
- 何时选择 ReentrantLock
- wait 与 sleep 对锁有什么不同
来源记录
- 原始来源
- 小林coding
- 来源页面
- 平安银行 Java 面试
- 最近收录
- 2026-07-05
- 官方复核
- Oracle Java 官方文档