synchronized底层实现分四层:字节码用monitorenter/monitorexit或acc_synchronized标志;锁绑定对象头mark word;依赖jvm的monitor对象(含owner、entrylist等);按无竞争→偏向锁→轻量级锁→重量级锁升级。

面试时讲清楚 synchronized 的底层实现,关键不是堆砌术语,而是分层讲逻辑:从字节码表现 → 锁对象本质 → 对象头结构 → Monitor 机制 → 锁升级路径。这样既体现理解深度,又让面试官看到你有体系化认知。
一、字节码层面:monitorenter / monitorexit 是核心指令
无论修饰方法还是代码块,synchronized 最终都由 JVM 指令支撑:
- 同步代码块:编译后插入 monitorenter(加锁)和 monitorexit(解锁)指令;异常时也会触发 monitorexit,保证锁必然释放
- 同步方法:不生成上述指令,而是在方法的 access flags 中标记 ACC_SYNCHRONIZED;JVM 调用该方法前自动加锁,返回后自动解锁
- 二者本质一致:都是基于“进入/退出 Monitor”语义,只是表现形式不同
二、锁的本质:依赖对象头 + Monitor 对象
synchronized 的锁不是凭空产生的,它绑定在 Java 对象上:
- 每个 Java 对象都有一个 对象头(Mark Word),其中包含锁状态位(如 001=无锁、101=偏向锁、00=轻量级锁、10=重量级锁)
- 当锁升级为重量级,Mark Word 会存储指向 操作系统级 Monitor 对象 的指针
- Monitor 是 JVM 在堆外创建的 C++ 对象,内部含 Owner(持有线程)、EntryList(等待队列)、WaitSet(等待 notify 的队列)等字段
三、锁升级过程:偏向 → 轻量级 → 重量级(JDK6+ 优化)
JVM 不会一上来就用重量级锁,而是按竞争程度逐步升级,降低开销:
- 偏向锁:假设“无竞争”,直接把线程 ID 记入 Mark Word;后续同一线程重入无需同步操作;一旦出现其他线程竞争,就撤销并升级
- 轻量级锁:多个线程交替执行,无真正阻塞;通过 CAS 尝试将 Mark Word 替换为指向线程栈中 Lock Record 的指针;失败则自旋重试,自旋次数超限就膨胀
- 重量级锁:竞争激烈时,锁对象关联 Monitor,未获取锁的线程进入 OS 级等待队列(挂起),由操作系统调度唤醒
四、被锁对象是谁?必须说清作用域
面试常考“锁的是谁”,答错容易暴露基础漏洞:
- 修饰实例方法或 synchronized(this):锁当前实例对象(this)
- 修饰静态方法或 synchronized(XXX.class):锁该类的 Class 对象
- 修饰代码块 synchronized(obj):锁 obj 引用的对象(必须非 null)
- 注意:实例锁和类锁互不干扰,可同时进入 —— 这是很多并发 bug 的根源
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











