文章目录
- [一、验证偏向锁(Biased Lock)](#一、验证偏向锁(Biased Lock))
- [二、验证轻量级锁(Lightweight Lock)](#二、验证轻量级锁(Lightweight Lock))
- [三、验证重量级锁(Heavyweight Lock)](#三、验证重量级锁(Heavyweight Lock))
- [四、总结:如何用 JOL 清晰地观察锁升级过程?](#四、总结:如何用 JOL 清晰地观察锁升级过程?)
如何用 Java Object Layout (JOL) 工具验证 Java 中 synchronized 的三种锁升级过程。
Maven 依赖:
xml
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.17</version>
</dependency>
一、验证偏向锁(Biased Lock)
⚠️ JVM 默认延迟偏向锁 4 秒
因此要么 -XX:BiasedLockingStartupDelay=0,要么 Thread.sleep 等待 4 秒。
java
public class JOLDemoBias {
static class A {}
public static void main(String[] args) throws Exception {
A a = new A();
System.out.println("无锁:");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
Thread.sleep(5000); // 等待偏向锁生效
synchronized (a) {
System.out.println("偏向锁:");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
}
观测点:

偏向锁时 mark word 的最后3 位是 101
并且会包含 ThreadId(偏向线程的 ID)。
二、验证轻量级锁(Lightweight Lock)
轻量级锁发生在 同一线程重复进入 synchronized,或多个线程竞争但没有阻塞时。
java
public class JOLDemoLight {
static class A {}
public static A a = new A();
public static void main(String[] args) throws Exception {
Thread.sleep(5000); // 偏向锁激活
synchronized (a) {
System.out.println("偏向锁:");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
Thread t1 = new Thread(() -> {
synchronized (a) {
System.out.println("轻量级锁:");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
});
t1.start();
t1.join();
}
}
观测点:

轻量级锁时 mark word 的最后3 位是 00
并且 mark word 指向线程栈中的 Lock Record(栈中一个 pointer)。
三、验证重量级锁(Heavyweight Lock)
多个线程竞争导致阻塞后,会升级为重量级锁。
java
public class JOLHeavyDemo {
static class A {}
static A a = new A();
public static void main(String[] args) throws Exception {
Thread.sleep(5000); // 偏向锁激活
System.out.println("初始:");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
Thread t1 = new Thread(() -> {
synchronized (a) {
try { Thread.sleep(2000); } catch (Exception ignored) {}
}
});
Thread t2 = new Thread(() -> {
synchronized (a) {
System.out.println("重量级锁:");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
});
t1.start();
Thread.sleep(100); // 保证 t1 先进入同步块
t2.start();
t1.join();
t2.join();
}
}
观测点:
重量级锁时:

- mark word 的最后 3 位是 10
- 其余部分存放一个指向 Monitor 对象(OS 层的 mutex) 的指针
表现为 JOL 输出里面出现:
monitor (owner ... )
四、总结:如何用 JOL 清晰地观察锁升级过程?
| 锁状态 | Mark Word 低三位 | 特征 |
|---|---|---|
| 无锁(Normal) | 001 | hash 未计算时更多空间用于 MarkWord |
| 偏向锁 | 101 | 有 ThreadId |
| 轻量级锁 | 00 | 指向线程栈中 Lock Record |
| 重量级锁 | 10 | 指向 Monitor 对象 |