monitorenter 是 jvm 字节码中触发对象监视器获取的指令,作用于运行时堆对象实例,按偏向锁、轻量级锁、重量级锁三级机制尝试加锁,并与 monitorexit 成对出现保障异常安全及可重入性。

monitorenter 是 JVM 执行 synchronized 代码块时插入的关键字底层指令,它不是 Java 语法,而是字节码层面的“抢锁开关”——真正触发对象监视器(Monitor)获取逻辑的起点。
monitorenter 的核心作用是尝试获取对象的 Monitor 所有权
它不锁变量,也不锁类定义,只对 运行时实际指向的堆对象 生效。比如:
- synchronized(obj) 中的 obj 必须是非 null 引用,否则 JVM 在执行 monitorenter 前就直接抛出 NullPointerException;
- 若 obj 后来被重新赋值为另一个对象,新旧对象的锁完全独立,互不影响;
- 锁的是对象实例本身(或 Class 对象),不是变量名,也不是栈上引用。
monitorenter 按优先级尝试三级锁机制
它不是一上来就挂起线程,而是按性能从高到低依次尝试:
- 偏向锁:对象未被锁且处于可偏向状态时,直接将当前线程 ID 写入对象头 Mark Word,零开销;
- 轻量级锁:存在竞争但不激烈时,在线程栈帧中创建 Lock Record,用 CAS 替换对象头,成功即进入临界区;
- 重量级锁:CAS 失败说明竞争激烈,JVM 将 Monitor 膨胀,线程进入操作系统 Mutex 队列阻塞等待。
monitorenter 必须与 monitorexit 成对出现,且异常安全
JVM 编译器会自动在所有可能出口插入 monitorexit,包括正常 return 和异常路径:
- 同步块内抛出未捕获异常时,仍能保证锁被释放,避免死锁;
- 反编译常看到两个 monitorexit:一个在正常流程末尾,一个在异常处理入口后;
- 这个双出口机制由字节码 Exception table 支持,比 try-finally 更底层、更可靠。
monitorenter 是可重入性的字节码基础
它通过 Monitor 内部的 entry count 计数器实现:
- 同一线程再次进入同一把锁的 synchronized 块,计数器 +1;
- 每次 monitorexit 减 1,只有减到 0 才真正释放 Monitor;
- 因此同一个线程可以嵌套进入多个 synchronized(obj) 块,不会自己阻塞自己。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











