批量重偏向是jvm对某类新分配对象直接偏向当前线程以避免重复撤销再偏向;批量撤销是当某类撤销次数超阈值(默认40次)时,全局禁用该类偏向锁。

Java 中偏向锁的批量重偏向(Bulk Rebias)与批量撤销(Bulk Revoke)是 HotSpot 虚拟机为缓解偏向锁在多线程竞争场景下性能退化而设计的优化机制,核心目标是避免单个对象频繁触发同步升级和锁状态切换带来的开销。它们不是由用户代码直接控制,而是 JVM 在运行时根据对象分配模式和锁竞争特征自动触发的。
批量重偏向:避免重复撤销再偏向
当某个类的大量新创建对象原本被偏向于线程 A,但后续实际由线程 B 频繁访问并触发了偏向锁撤销(即进入轻量级锁),JVM 会检测到该类存在“偏向失效集中发生”的现象。此时,若满足条件(如类的 rebiased_count 达到阈值、且距上次批量操作已过一定时间),JVM 会对该类**尚未被访问过的所有新分配对象**,直接将 Mark Word 的偏向线程 ID 设为线程 B(或当前请求线程),跳过“先偏向 A、再撤销、再偏向 B”的三步过程。
- 触发时机依赖类级别的统计信息(如
BiasedLocking::revocation_counts和klass->last_biased_lock_bulk_revoke_time) - 仅作用于该类后续新分配的对象,已存在的对象不受影响(除非显式调用
Object#hashCode()或发生竞争) - 本质是“预测性偏向”——基于历史访问模式,提前把偏向权交给更可能持有锁的线程
批量撤销:彻底关闭某类的偏向锁
当一个类的对象频繁遭遇竞争(例如多个线程交替获取同一类实例的锁),导致大量偏向锁被撤销并升级为轻量级锁,JVM 会判定该类“不再适合使用偏向锁”。此时触发批量撤销:对该类及其所有已分配对象(包括已偏向和未偏向的),统一清除偏向标志位,并设置为“不可偏向”状态(mark word 中的 biased_lock bit = 0),后续新建对象也不再默认启用偏向锁。
- 判断依据包括:该类对象的撤销次数超过阈值(默认 20 次,由
-XX:BiasedLockingBulkRevokeThreshold控制)、且发生在短时间内 - 撤销动作由安全点(Safepoint)内的
BulkRevokeBias任务完成,需暂停所有 Java 线程 - 一旦类被批量撤销,该类全局禁用偏向锁,直到下次 JVM 启动(可通过
-XX:+UnlockDiagnosticVMOptions -XX:+PrintBiasedLockingStatistics查看统计)
关键实现载体:Klass 结构与安全点协作
批量操作的决策与执行高度依赖 Klass 元数据结构中维护的状态字段(如 _prototype_header、_biased_lock_revocation_count、_last_biased_lock_bulk_revoke_time),以及安全点机制保障一致性:
- 类元数据驱动:每个类有自己的偏向锁策略开关,而非按对象粒度管理
- 安全点同步:批量重偏向/撤销必须在所有线程到达安全点后执行,确保无正在执行的偏向锁操作
- 延迟生效:批量重偏向不修改已有对象,只影响新分配对象;批量撤销则需遍历所有已分配对象(通过对象遍历器),代价较高
如何观察与调试这些行为
可通过 JVM 参数开启诊断输出,验证是否触发批量操作:
-
-XX:+PrintBiasedLockingStatistics:输出各类偏向锁统计(撤销次数、批量操作次数等) -
-XX:+UnlockDiagnosticVMOptions:解锁诊断选项(必需配合上一条) -
-XX:BiasedLockingStartupDelay=0:取消启动延迟,让偏向锁尽早启用(便于测试) - 结合 JFR(Java Flight Recorder)或 hs_err 日志中的 Safepoint 日志,定位批量操作发生时刻
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











