java synchronized锁升级内存开销极轻:无锁零开销;偏向锁仅复用对象头;轻量级锁每线程栈中增8–16字节lock record;重量级锁才在堆中创建200+字节monitor并占用内核资源。

Java 中 synchronized 锁升级各阶段的内存开销,主要体现在对象头(Mark Word)的结构变化和线程栈的额外占用上,而非堆内存的显著增长。不同阶段对内存的影响差异明显,但整体非常轻量——关键不是“占多少内存”,而是“如何用更少的资源避免更重的代价”。
无锁状态:零额外开销
对象刚创建时,Mark Word 存储的是哈希码、GC分代年龄、是否为偏向锁标志等基础信息(锁标志位为 01)。此时完全不涉及锁逻辑,也不分配任何锁相关结构,无额外内存消耗。
偏向锁:仅对象头 + 少量元数据
当第一个线程获取锁时,JVM 将 Mark Word 改写为偏向锁格式(标志位变为 101),其中嵌入:
• 当前线程 ID(通常 54 位)
• 偏向时间戳(epoch,用于批量撤销)
• GC 分代年龄等保留字段
不新增对象或栈帧,只复用原有对象头空间。即使开启偏向锁(默认 JDK 15+ 已禁用,但逻辑仍存在),内存开销仍可忽略。
轻量级锁:每个竞争线程在栈中分配 Lock Record
发生竞争后,偏向锁撤销,进入轻量级锁状态(标志位 00)。此时:
• 每个尝试获取锁的线程,需在自己的 Java 栈帧中开辟一个 Lock Record 结构(约 8–16 字节,含 owner 指针、displaced mark word 等)
• 对象头被替换为指向该 Lock Record 的指针
• 若多个线程同时自旋,就对应多个 Lock Record,但仅限于活跃竞争线程的栈空间,不堆内存分配
• 自旋失败后 Lock Record 随栈帧销毁,无长期内存残留
重量级锁:Monitor 对象 + 内核资源映射
升级为重量级锁(标志位 10)后,内存开销明显上升:
• JVM 在堆中为该对象首次创建一个 ObjectMonitor(Monitor)对象(约 200+ 字节,含 _owner、_WaitSet、_EntryList 等字段)
• Monitor 内部关联操作系统互斥量(Mutex)和条件变量(Condition Variable),这部分由 OS 在内核态分配,不计入 Java 堆,但会占用进程的 native memory
• 被阻塞的线程转入 WAITING/TIMED_WAITING 状态,其线程栈保持活跃,但不再自旋,CPU 开销下降,内存占用稳定
锁升级本身不导致对象膨胀或数组扩容,所有变化都围绕 Mark Word 和少量栈/堆辅助结构展开。真正影响系统资源的,是重量级锁引发的线程阻塞与上下文切换——那属于 CPU 和调度开销,而非单纯内存问题。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











