先抛一个核心结论:偏向锁撤销这件事,远比“改个标志位”要复杂。它会强制所有 Ja va 线程停在安全点(Safepoint),形成一次全局同步停顿。这个过程不看锁竞争是否激烈,只看 JVM 是否需要修改对象头并确认线程状态。一旦触发,所有线程都得等,哪怕只有一个对象被撤销,后果也是全局性的。

为什么撤销必须等所有线程进 Safepoint

偏向锁的状态依赖于线程私有的信任机制:原持有线程的栈帧里,可能正隐式跳过 CAS,直接复用偏向 ID。JVM 可不敢在任意时刻强行覆盖 Mark Word,否则会导致该线程后续重入时状态错乱。所以,必须等每个线程自己走到一个可检查的位置——比如方法返回、循环边界、字节码间歇点——再统一暂停、遍历栈帧、判断是否还在同步块中。

撤销如何污染整类对象的锁行为

JVM 不是按对象统计撤销次数,而是按 Class 统计。只要同一类的对象被撤销达到阈值,后续所有新实例都会被“连坐”——要么批量重偏向,要么直接禁用偏向锁。

hashCode() 是最隐蔽的撤销诱因

很多开发者没意识到,只要对象调用了 hashCode(),JVM 就必须把 Mark Word 中存储的线程 ID 替换为哈希值——这直接导致偏向锁失效,触发一次完整撤销流程。

生产环境更可靠的应对方式

与其花时间调参或排查哪段代码触发了撤销,不如直接关闭偏向锁。现代多核服务中,它的收益早已被 STW 代价彻底抵消。

本文转载于:https://www.php.cn/faq/2462577.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。