java中synchronized的偏向锁和轻量级锁是jdk 1.6起为减少无/低竞争锁开销的优化,依托对象头mark word变化、纯用户态实现;偏向锁适用于单线程反复进入场景,首次cas设置线程id,后续直接比对id免cas;有竞争则撤销并升级为轻量级锁;轻量级锁通过栈中lock record和cas抢占,失败自旋后升级重量级锁;锁状态全存mark word,升级路径单向:无锁→偏向锁→轻量级锁→重量级锁。

Java 中 synchronized 的偏向锁和轻量级锁是 JVM(JDK 1.6 起)为减少无竞争或低竞争场景下锁开销而做的优化,它们都依托于对象头(Mark Word)的结构变化,不依赖操作系统互斥量,全程在用户态完成。
偏向锁:单线程长期持有时的零成本进入
偏向锁适用于“一个同步块几乎总是被同一个线程反复进入”的场景,比如单例初始化、线程局部缓存访问等。
- 当第一次有线程进入
synchronized块时,JVM 检查对象头是否处于无锁状态(Mark Word 标志位为 01,且偏向锁标志为 0),满足则通过 CAS 将其置为偏向锁状态(标志位 101),并写入当前线程 ID 和 epoch 时间戳 - 后续该线程再次进入同一同步块,只需比对对象头中的线程 ID 是否与自己一致,一致就直接执行,完全跳过 CAS 和锁获取逻辑
- 一旦有其他线程尝试获取该锁,就会触发偏向撤销:持有偏向锁的线程会暂停(安全点),JVM 将锁升级为轻量级锁,并将原偏向信息迁移至栈帧中的锁记录(Lock Record)
- 默认开启,可通过
-XX:-UseBiasedLocking关闭;在应用启动几十秒后(默认延迟 4 秒),JVM 会批量撤销尚未被竞争的偏向锁,避免长期无效偏向
轻量级锁:多线程交替执行、无真实竞争时的快速抢占
轻量级锁用于多个线程可能访问同一同步块,但不会同时抵达的场景,比如方法调用链中短暂的临界区。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 线程在栈帧中创建一个 Lock Record(锁记录),初始化为对象头的原始 Mark Word 内容
- 通过 CAS 尝试将对象头的 Mark Word 替换为指向该 Lock Record 的指针;成功即获得锁,标志位设为 00
- 若 CAS 失败(说明已有其他线程抢先设置),当前线程会自旋若干次(默认 10 次,由
-XX:PreBlockSpin控制),等待锁释放;若仍失败,则升级为重量级锁 - 释放锁时,线程用 CAS 将 Lock Record 中保存的原始 Mark Word 写回对象头;若失败(说明已升级),则执行重量级锁的唤醒逻辑
锁升级是单向的,且由对象头驱动
锁的状态全部编码在对象头的 Mark Word 中,32 位 JVM 下典型布局如下:
- 无锁:标志位 01,高位存 hashCode 或分代年龄
- 偏向锁:标志位 101,含线程 ID、epoch、年龄
- 轻量级锁:标志位 00,存指向栈中 Lock Record 的指针
- 重量级锁:标志位 10,存指向 OS Mutex 的指针
升级路径固定为:无锁 → 偏向锁 → 轻量级锁 → 重量级锁。没有降级机制,因为撤销偏向或膨胀为重量级锁的代价已远高于维持当前状态。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










