MST

星途 面试题库

面试题:Java JVM 线程管理中的锁优化策略

在 Java JVM 线程管理场景下,常常会涉及到锁机制,为了提升性能需要对锁进行优化。请描述至少三种常见的锁优化策略,并说明每种策略适用的场景。
30.3万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 减少锁的粒度
    • 策略描述:将大对象(可能被多个线程访问)拆分成多个小对象,每个小对象单独加锁。这样不同线程可以同时访问不同的小对象,从而减少锁竞争。
    • 适用场景:适用于对象包含多个相对独立的部分,且不同部分被不同线程访问概率较高的场景。比如在一个电商系统中,商品对象包含商品基本信息、库存信息、价格信息等,不同业务模块对这些信息的操作相对独立,就可以对每个部分分别加锁。
  2. 锁粗化
    • 策略描述:如果一系列的连续操作都对同一个对象反复加锁和解锁,甚至加锁操作出现在循环体中,此时可以将加锁的范围扩展(粗化)到整个操作序列的外部。这样减少了加锁解锁的次数,提升性能。
    • 适用场景:适用于在一段代码中,频繁对同一对象进行加锁解锁操作的场景。例如,在一个方法中多次调用同一个对象的同步方法,就可以考虑锁粗化。
  3. 偏向锁
    • 策略描述:偏向锁是为了在无竞争情况下减少锁获取的开销。当一个线程访问同步块并获取锁时,会在对象头中记录这个线程的 ID,以后该线程再次进入和退出同步块时,不需要进行 CAS 操作来加锁和解锁,只需要简单判断对象头的偏向锁标志位和线程 ID。
    • 适用场景:适用于大部分时间只有一个线程访问同步块的场景。比如单线程环境下,或者在一个线程长时间持有锁的情况下,偏向锁能显著提升性能。
  4. 轻量级锁
    • 策略描述:当锁是偏向锁时,来了第二个线程访问同步块,偏向锁就会升级为轻量级锁。轻量级锁在竞争不是特别激烈的情况下,通过 CAS 操作来尝试获取锁,避免了重量级锁使用操作系统互斥量带来的性能开销。
    • 适用场景:适用于竞争不太激烈的场景,线程交替执行同步块的情况比较多,使用轻量级锁能减少线程阻塞和唤醒带来的开销。
  5. 自旋锁
    • 策略描述:当一个线程尝试获取锁时,如果锁已经被其他线程持有,该线程不会立即阻塞,而是在原地循环等待一段时间,在这段时间内不断尝试获取锁,希望在等待期间持有锁的线程能释放锁,从而避免线程上下文切换的开销。
    • 适用场景:适用于锁被持有时间较短,线程竞争不激烈的场景。因为如果自旋时间过长,反而会浪费 CPU 资源,不如直接阻塞线程。例如在一些简单的同步代码块,执行时间很短,自旋锁能有效提升性能。