主题
面试速答(先看这里)
**一句话结论:**在过去,Java 应用通常使用的都是 HashTable、Vector 等比较老的集合库,这类集合库大量使用了 synchronized 来保证线程安全。
60秒标准回答:
在JDK 1.7中,引入了偏向锁的概念来优化synchronized的性能,但是偏向锁,在JDK 15中已经被废弃了。那么,为什么呢?( )
JDK 15决定废弃偏向锁的主要原因是
在过去,Java 应用通常使用的都是 HashTable、Vector 等比较老的集合库,这类集合库大量使用了 synchronized 来保证线程安全。所以偏向锁技术作为synchronized的一种优化手段,可以减少无锁竞争情况下的开销,通过假定一个锁一直由同一线程拥有,从而避免执行比较和交换的原子操作
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **要点1:**在JDK 1.7中,引入了偏向锁的概念来优化synchronized的性能,但是偏向锁,在JDK 15中已经被废弃了。
- **要点2:**JDK 15决定废弃偏向锁的主要原因是:
- **要点3:**但是,偏向锁的局限是当只有一个线程反复进入同步代码块时他才能快速获得,但是当有其他线程尝试获取锁的时候,就需要等到 safe point 时,再将偏向锁撤销为无锁的状态或者升级为轻量级锁,而这个过程其实是会消耗一定的性能的。
- **要点4:**在高并发的场景下,频繁的撤销偏向锁和重新偏向不仅不能提升性能,还会导致性能下降,特别是在那些锁竞争较为激烈的应用中。
- **要点5:**并且,随着Java应用程序的发展和优化,过去能够从偏向锁中获得的性能提升在当今的应用中不再明显。
**记忆锚点:**synchronized → JDK → Java → 废弃偏向锁 → 偏向锁 → CopyOnWriteArrayList
关键取舍:
- 在JDK 1.7中,引入了偏向锁的概念来优化synchronized的性能,但是偏向锁,在JDK 15中已经被废弃了。
- 但是,偏向锁的局限是当只有一个线程反复进入同步代码块时他才能快速获得,但是当有其他线程尝试获取锁的时候,就需要等到 safe point 时,再将偏向锁撤销为无锁的状态或者升级为轻量级锁,而这个过程其实是会消耗一定的性能的。
- 在高并发的场景下,频繁的撤销偏向锁和重新偏向不仅不能提升性能,还会导致性能下降,特别是在那些锁竞争较为激烈的应用中。
易错提醒:
- 所以偏向锁技术作为synchronized的一种优化手段,可以减少无锁竞争情况下的开销,通过假定一个锁一直由同一线程拥有,从而避免执行比较和交换的原子操作。
- 在高并发的场景下,频繁的撤销偏向锁和重新偏向不仅不能提升性能,还会导致性能下降,特别是在那些锁竞争较为激烈的应用中。
追问准备:
- 围绕「synchronized」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「JDK」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「Java」:底层原理是什么?使用时有哪些边界和常见坑?
- 如果线上出现异常,你会如何定位、验证并规避?
典型回答
在JDK 1.7中,引入了偏向锁的概念来优化synchronized的性能,但是偏向锁,在JDK 15中已经被废弃了。那么,为什么呢?(https://openjdk.org/jeps/374 )
JDK 15决定废弃偏向锁的主要原因是:
在过去,Java 应用通常使用的都是 HashTable、Vector 等比较老的集合库,这类集合库大量使用了 synchronized 来保证线程安全。所以偏向锁技术作为synchronized的一种优化手段,可以减少无锁竞争情况下的开销,通过假定一个锁一直由同一线程拥有,从而避免执行比较和交换的原子操作。
但是,偏向锁的局限是当只有一个线程反复进入同步代码块时他才能快速获得,但是当有其他线程尝试获取锁的时候,就需要等到 safe point 时,再将偏向锁撤销为无锁的状态或者升级为轻量级锁,而这个过程其实是会消耗一定的性能的。
在高并发的场景下,频繁的撤销偏向锁和重新偏向不仅不能提升性能,还会导致性能下降,特别是在那些锁竞争较为激烈的应用中。
并且,随着Java应用程序的发展和优化,过去能够从偏向锁中获得的性能提升在当今的应用中不再明显。许多现代应用程序使用了不需要同步的集合类或更高性能的并发数据结构(如ConcurrentHashMap、CopyOnWriteArrayList等),而不再频繁地执行无争用的同步(synchronized)操作。
还有就是官方在文档中提到的,偏向锁的引入导致代码很复杂,给HotSpot虚拟机中锁相关部分与其他组件之间的交互也带来了复杂性。这种复杂性使得理解代码的各个部分变得困难,并且阻碍了在同步子系统内进行重大设计更改。因此,废弃偏向锁有助于减少复杂性,使代码更容易维护和改进。
总之,废弃偏向锁是为了减少复杂性、提高代码可维护性,并鼓励开发人员采用更现代的并发编程技术,以适应当今Java应用程序的性能需求。