synchronized 是Java原生最核心的同步原语,早期因“重量级锁”的高开销被诟病,JDK 1.6 引入的锁升级机制,让它能根据竞争场景自适应切换锁状态,性能实现质的飞跃,是并发编程必须吃透的底层逻辑。
一、锁的底层载体
synchronized 的底层依托于 Java对象头(Mark Word) 与管程(Monitor)实现。
Java对象的Mark Word会动态存储锁状态、持有线程ID、偏向时间戳、分代年龄等信息,锁升级的本质,就是Mark Word在不同竞争场景下的状态流转,全程仅支持升级、不支持降级(仅偏向锁可撤销)。
二、完整的锁升级链路
JVM会根据竞争激烈程度,逐级升级锁,全程无人工干预,适配绝大多数业务场景。
无锁状态
对象刚创建、未被任何线程竞争时,Mark Word处于无锁状态,仅存储对象的哈希码、分代年龄等基础信息。偏向锁(无竞争场景)
这是JVM的极致优化:锁首次被单个线程访问时,会通过CAS将该线程ID写入Mark Word,标记为偏向锁。后续该线程进入同步块时,无需任何CAS加锁/解锁操作,几乎零开销。
它解决了现实中“90%的锁全程只有一个线程持有”的场景,彻底消除无竞争场景下的同步开销。轻量级锁(轻度竞争场景)
当出现第二个线程竞争锁时,偏向锁立即撤销,升级为轻量级锁。
竞争线程会通过自适应CAS自旋尝试获取锁,全程在用户态执行,无内核态切换,不会阻塞线程。JVM会根据历史自旋成功率动态调整自旋次数,避免CPU空耗。重量级锁(高强度竞争场景)
当自旋多次失败、多线程同时竞争、锁持有时间过长时,轻量级锁会立即升级为重量级锁。
此时锁会关联对象的Monitor管程,未抢到锁的线程会进入阻塞队列,发生用户态与内核态的切换,开销最高,但不会持续占用CPU,适合高竞争、长耗时的同步场景。
三、核心认知误区与最佳实践
- 常见误区:
synchronized一上来就是重量级锁。事实上JDK 1.6+默认开启锁升级,会根据竞争程度自适应切换,绝大多数低竞争场景下开销极低。 - 核心禁忌:同步块尽量精简,避免锁持有时间过长,导致锁快速升级到重量级锁;高并发场景需合理拆分锁粒度,降低竞争强度。
结语
synchronized 的锁升级机制,是JVM对现实并发场景的极致工程优化,兼顾了无竞争场景的低开销与高竞争场景的稳定性。理解它的底层逻辑,不仅能写出更高效的并发代码,更是排查并发死锁、性能瓶颈的核心前提。