JEP 374:弃用并禁用偏向锁
总结
默认情况下禁用偏向锁,并弃用所有相关的命令行选项。
目标
确定是否需要继续支持传统的偏向锁同步优化,因为维护成本很高。
动机
偏向锁是 HotSpot 虚拟机中使用的一种优化技术,旨在减少无竞争锁的开销。它通过假设一个监视器(monitor)始终由某个线程拥有,直到另一个线程尝试获取它,从而避免在获取监视器时执行比较并交换(compare-and-swap)原子操作。监视器的初始锁定会将监视器偏向于该线程,从而避免在后续针对同一对象的同步操作中使用原子指令。当许多线程对以单线程方式使用的对象执行大量同步操作时,与常规锁定技术相比,偏向锁在历史上带来了显著的性能提升。
过去能看到的性能提升在今天已经不那么明显了。许多从偏向锁中受益的应用程序是较旧的遗留应用程序,它们使用早期的 Java 集合 API,每次访问都会进行同步(例如,Hashtable
和 Vector
)。较新的应用程序通常会使用非同步集合(例如,HashMap
和 ArrayList
),这些集合是在 Java 1.2 中为单线程场景引入的,或者是性能更高的并发数据结构,这些是在 Java 5 中为多线程场景引入的。这意味着,如果代码更新为使用这些较新的类,那些因不必要的同步而从偏向锁中受益的应用程序可能会看到性能提升。此外,围绕线程池队列和工作线程构建的应用程序在禁用偏向锁的情况下通常表现更好。(SPECjbb2015 就是这样设计的,例如,而 SPECjvm98 和 SPECjbb2005 则不是)。偏向锁的代价是在发生争用时需要执行昂贵的撤销操作。因此,只有那些表现出大量无争用同步操作的应用程序才能从中受益,就像上面提到的那样,这样执行廉价的锁持有者检查加上偶尔昂贵的撤销操作的成本仍然低于执行规避的比较并交换原子指令的成本。自偏向锁引入 HotSpot 以来,原子指令成本的变化也改变了保持这种关系所需的无争用操作的数量。另一个值得注意的方面是,即使之前的成本关系成立,当花在同步操作上的时间仍然只占整个应用程序工作负载的一小部分时,应用程序也不会有明显的性能提升。
偏向锁在同步子系统中引入了大量的复杂代码,并且对其他 HotSpot 组件也具有侵入性。这种复杂性成为理解代码各个部分的障碍,同时也阻碍了在同步子系统中进行重大的设计更改。鉴于此,我们希望禁用、弃用并最终移除对偏向锁的支持。
描述
在 JDK 15 之前,偏向锁始终是启用并可用的。通过此 JEP,除非在命令行中设置了 -XX:+UseBiasedLocking
,否则在启动 HotSpot 时将不再启用偏向锁。
我们将弃用 UseBiasedLocking
选项以及与偏向锁配置和使用相关的所有选项。
- 产品选项:
BiasedLockingStartupDelay
、BiasedLockingBulkRebiasThreshold
、BiasedLockingBulkRevokeThreshold
、BiasedLockingDecayTime
和UseOptoBiasInlining
- 诊断选项:
PrintBiasedLockingStatistics
和PrintPreciseBiasedLockingStatistics
这些选项仍然会被接受并执行,但会发出弃用警告。
风险与假设
某些 Java 应用程序在禁用偏向锁后可能会出现性能下降。允许在命令行重新启用偏向锁有助于缓解此问题,并提供可能的洞察,了解哪些情况仍可能从其使用中受益。