Skip to main content

偏向锁

UseBiasedLocking 是 Java 虚拟机(JVM)中的一个选项,用于启用或禁用偏向锁(Biased Locking)机制,偏向锁是一种优化机制,旨在提高 单线程程序的性能。

偏向锁的作用

  1. 提高性能:
  • 偏向锁是为了减少 锁竞争,尤其是在多线程环境下,锁的获取和释放操作通常会消耗大量资源。
  • 偏向锁的核心思想是:如果一个线程几乎始终独占某个对象的锁,那么 JVM 会认为该线程会长期持有这个锁,而不需要每次都进行锁竞争。
  1. 原理:
  • 当一个线程第一次访问某个对象时,它会将该对象的锁 “偏向” 给自己。之后,如果这个线程再次访问这个对象,它就不需要进行锁的获取操作,直接使用之前的锁。
  • 只有当其他线程尝试访问这个对象时,偏向锁才会被撤销,锁会转变为轻量级锁或重量级锁,具体取决于竞争的情况。
  1. 提高效率的情境:
  • 偏向锁主要针对那些大多数情况下只有一个线程访问的对象。对于 单线程程序 或 多线程中只有一个线程频繁访问某个对象 的情况,偏向锁能够显著减少锁的开销。

为什么要禁用偏向锁

  • JDK 21+ 移除偏向锁:偏向锁虽然在性能优化上有其优势,但随着多核处理器的发展和现代 JVM 的优化,偏向锁在多核处理器上的效果逐渐降低,甚至在某些场景下可能导致额外的开销。 因此,JDK 21 及以上版本移除了偏向锁,并推荐使用 轻量级锁 和 自旋锁 等机制,来代替偏向锁。

偏向锁诞生于 2000 年代初(JDK 6 时代)。那时候 Java 开发者还在大量使用遗留的旧代码和早期集合类,比如 Vector、Hashtable 和 StringBuffer。 这些老旧的类每个方法都自带 synchronized。 如果用户在单线程里使用它们,就会产生大量无竞争的锁开销,偏向锁就是为了拯救这些老代码而设计的。 但到了今天: 现代 Java 开发者写单线程代码会用 ArrayList、HashMap、StringBuilder,它们根本没有锁。 写多线程高并发代码会用 java.util.concurrent(如 ConcurrentHashMap、LongAdder)或者高级并发框架。 也就是说:需要锁的地方通常竞争激烈,不需要竞争的地方根本就没锁。 偏向锁能够发挥作用的“真空地带”几乎不存在了。

JDK 21 及以上版本

  • 在 JDK 21+ 中,UseBiasedLocking 被移除,因此如果你使用的是 JDK 21 或更高版本,启动 JVM 时会看到 “Unrecognized VM option ‘UseBiasedLocking’” 错误。

总结

  • 偏向锁用于减少单线程程序中的锁竞争,提高性能。
  • JDK 21 及以上版本移除了偏向锁,JVM 不再支持 UseBiasedLocking 选项。
  • 如果你在 JDK 21 及以上版本 中看到此错误,可以安全地移除该选项,因为它已经不再被使用。