Epoch 是偏向锁的“有效期标签”,本质为类元数据与对象Mark Word中存储的整数时间戳,由JVM批量重偏向时递增;当类epoch与对象epoch不等时,新线程可直接CAS重偏向,避免全局停顿。
Epoch 是偏向锁的“有效期标签”
epoch 本质上是一个时间戳,存储在类元数据(class metadata)和每个可偏向对象的 mark word 中。它不记录绝对时间,而是每次批量重偏向时由 jvm 主动递增的一个整数值。所有属于该类的对象,在创建时都会把当前 class 的 epoch 值复制到自己的 mark word 里。这样,对象和它所属的类就共享同一个“版本号”。
批量重偏向靠 Epoch 差值触发重偏向判断
当某个类的偏向锁撤销次数达到阈值(默认 20 次),JVM 认为“这个类的对象频繁换线程持有,但又不并发”,适合批量重偏向。此时会在安全点执行以下操作:
- 将该 class 的 epoch 值加 1,生成新的 epoch_new
- 扫描所有该类实例,但只更新那些正被线程锁定的对象的 Mark Word 中的 epoch 字段为 epoch_new
- 退出安全点后,新线程尝试获取偏向锁时,会比对:当前 class 的 epoch 与目标对象 Mark Word 中的 epoch 是否相等
- 如果不等,说明该对象的偏向已过期,允许当前线程直接执行 CAS 将其重偏向到自己,无需先撤销再重设
Epoch 避免了逐个对象撤销的开销
没有 Epoch 机制时,每次有新线程争用,都得暂停持有锁的线程、检查栈帧、清除旧偏向、再设新偏向——成本高且需全局安全点。而 Epoch 通过“一次递增 + 懒更新”的方式,让大多数对象在下次被访问时才自然完成重偏向,既避免了立即停顿,又保证了语义正确性。它不是实时同步所有对象,而是用一次 class 级别变更,驱动后续所有访问按需刷新。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
Epoch 还隔离了不同批次的偏向状态
比如线程 T1 在 epoch=1 时获得偏向,之后发生批量重偏向使 class epoch 变为 2;再过一阵又触发一次,epoch 变为 3。此时对象 Mark Word 中残留的是 1 或 2,都能被准确识别为“过期”,不会误判为当前有效。这种版本号机制天然支持多次重偏向,也防止了因 GC 或对象复用导致的跨代偏向混淆。

















