重量级锁和轻量级锁是synchronized在不同竞争强度下的动态状态,由jvm自动升级:轻量级锁通过cas+自旋避免内核态切换,自旋失败则升级为重量级锁,后者借助操作系统mutex挂起线程,保障高竞争下的安全与公平,且升级不可逆。

Java 中的重量级锁和轻量级锁不是独立配置的两种锁,而是同一把 synchronized 锁在不同竞争强度下动态呈现的**状态**。升级过程完全由 JVM 自动完成,核心目标是:**无竞争时零开销,轻度竞争时避免内核态切换,重度竞争时保障公平与安全**。
轻量级锁如何工作:用自旋代替阻塞
当偏向锁被撤销(比如第二个线程来抢锁),或对象初始就不支持偏向锁时,JVM 就会尝试使用轻量级锁:
- 线程在自己的栈帧中创建一个 Lock Record(锁记录),里面存有当前对象 Mark Word 的拷贝
- 通过 CAS 操作,尝试把对象头的 Mark Word 替换为指向该 Lock Record 的指针(标志位设为 00)
- 若 CAS 成功,表示抢锁成功;失败则说明已有其他线程在竞争,进入自旋等待
- 自旋不是无限的——JVM 根据历史表现自适应调整次数(默认约 10 次),超时仍未获取到锁,就触发升级
重量级锁何时登场:从自旋到挂起
当轻量级锁的自旋失败、竞争持续加剧,JVM 就会把锁“膨胀”为重量级锁:
- 对象头 Mark Word 被更新为指向一个 ObjectMonitor 结构体的指针(标志位变为 10)
- ObjectMonitor 是 JVM 在堆上分配的同步原语,内部包含
_owner(持有者)、_entryList(等待获取锁的线程队列)、_waitSet(调用wait()的线程队列)等字段 - 后续竞争线程不再自旋,而是被
pthread_mutex_lock等系统调用挂起,进入操作系统调度队列,等待被唤醒 - 此时发生用户态 → 内核态切换,上下文切换开销显著上升(微秒级),但换来的是 CPU 资源释放和更稳定的线程调度
升级不可逆,但优化不止于升级
锁一旦升级为重量级,就不会再降回轻量级或偏向锁——这是为了简化状态管理、避免反复判断带来的额外开销。不过 JVM 还配套了其他优化手段来缓解重量级锁压力:
- 锁消除:JIT 编译器通过逃逸分析发现某个锁对象只在单线程内使用,直接删掉同步逻辑
- 锁粗化:把多个连续的小同步块合并成一个大同步块,减少频繁加锁/解锁次数
- 自适应自旋:并非固定次数,而是根据前几次自旋是否成功动态调整,提升命中率
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











