要查 synchronized 锁状态,需运行时观测对象头:用 jol 打印 mark word 二进制位(01+线程id=偏向锁,00=轻量级锁,10=重量级锁);配合 jvm 日志参数(如 -xx:+tracebiasedlocking)跟踪升级过程;jstack -l 查持有状态(biased/inflated);通过 -xx:-/+usebiasedlocking 开关对比验证。

要查清楚 synchronized 锁当前处于哪种状态(无锁、偏向锁、轻量级锁还是重量级锁),不能靠看代码或字节码,得结合运行时工具和 JVM 日志。核心思路是:**对象头内容决定锁状态,而对象头只能在运行时观测**。
用 jol 工具直接打印对象头
Java Object Layout(jol)是最直观的方式,能显示 Mark Word 的二进制布局,从而判断锁状态。
- 添加依赖:
org.openjdk.jol:jol-core:0.16 - 在同步块前后分别打印同一对象的对象头:
Object obj = new Object();
System.out.println("未加锁:" + ClassLayout.parseInstance(obj).toPrintable());
synchronized (obj) {
System.out.println("加锁后:" + ClassLayout.parseInstance(obj).toPrintable());
}
}
输出中重点关注 Mark Word 的最后 2–3 位标志位:
• 01 且含线程 ID → 偏向锁
• 00 → 轻量级锁(指向栈中 Lock Record)
• 10 → 重量级锁(指向 Monitor 对象)
开启 JVM 锁诊断日志
通过参数让 JVM 主动输出锁状态变化过程,适合分析升级触发时机。
- 关键参数组合:
-XX:+PrintBiasedLockingStatistics
-XX:+TraceBiasedLocking
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1
启用后,控制台会打印类似:
[BiasedLocking] Revoking bias of object 0x0000000712345000, thread Thread-1, epoch 0
这类日志说明偏向锁被撤销,即将升级;配合 -XX:+PrintSynchronization 还能看到 monitorenter 的调用上下文。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
用 jstack 查看线程持有状态
对运行中的 Java 进程执行 jstack -l <pid></pid>,搜索 locked 关键字。
- 看到
locked (a java.lang.Object) (biased)→ 当前为偏向锁 - 看到
(inflated)→ 已膨胀为重量级锁 - 没有特别标注,默认可能是轻量级锁或偏向锁(需结合 jol 确认)
注意:jstack 只反映“当前是否被持有”及粗略类型,不展示升级路径,但可快速定位高竞争锁源。
禁用/启用偏向锁做对比验证
偏向锁在 JDK 15+ 默认关闭,但在 JDK 8–14 中默认开启。可通过开关验证其影响:
- 临时关闭:
-XX:-UseBiasedLocking→ 强制跳过偏向锁阶段,直接走轻量级锁路径 - 显式开启:
-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0→ 避免启动延迟导致初期测不到偏向效果
搭配 JMH 基准测试,可量化不同锁状态下的吞吐差异,比如单线程场景下关闭偏向锁通常会使 synchronized 方法慢 5–10%。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










