MST

星途 面试题库

面试题:Java线程安全中的锁优化策略

在高并发的Java应用中,锁的使用对性能影响很大。请阐述几种常见的锁优化策略,如锁粗化、锁消除、偏向锁、轻量级锁等,说明它们是如何工作的,在什么场景下会生效,以及使用这些策略时可能面临的问题。
30.0万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

锁粗化

  • 工作原理
    • 将多次连续的加锁、解锁操作合并为一次,扩大锁的作用范围。比如在一个循环中多次对同一对象加锁解锁,JVM 会将这些操作优化为在循环外部加锁一次,循环结束后解锁一次。
  • 生效场景
    • 当一系列连续操作都对同一个锁对象进行加锁解锁,且中间没有其他线程竞争该锁时,锁粗化能减少频繁加锁解锁带来的性能开销。
  • 可能面临的问题
    • 锁粗化后,锁的持有时间变长,如果有其他线程竞争锁,会导致其他线程等待时间增加,降低系统的并发性能。

锁消除

  • 工作原理
    • JVM 编译器在编译时,通过逃逸分析判断一个对象是否不会被其他线程访问,如果不会,则消除对该对象的加锁操作。例如一个局部对象,其只在方法内部使用,没有被其他线程访问的可能,那么对该对象的加锁操作会被消除。
  • 生效场景
    • 适用于对象的使用范围局限在单个线程内,没有逃逸出该线程的场景。这种情况下,锁操作实际上是不必要的,锁消除可以避免无谓的锁开销。
  • 可能面临的问题
    • 如果逃逸分析不准确,误将可能被其他线程访问的对象的锁消除,会导致线程安全问题。

偏向锁

  • 工作原理
    • 偏向锁是为了在无竞争情况下减少锁获取的开销。当一个线程访问加锁对象时,会在对象头中记录该线程的 ID,以后该线程再次访问该对象时,发现对象头中的线程 ID 是自己的,则无需进行额外的加锁操作,直接进入同步块。只有当其他线程尝试访问该对象时,偏向锁才会被撤销,升级为轻量级锁。
  • 生效场景
    • 适用于锁基本总是由同一个线程多次获取的场景,如单线程频繁访问某个加锁资源。这种情况下,偏向锁能极大提高性能,因为避免了每次加锁的开销。
  • 可能面临的问题
    • 如果实际应用场景中锁竞争频繁,偏向锁不断被撤销和升级,会带来额外的性能开销。而且偏向锁的撤销需要等待全局安全点,可能会导致短暂的停顿。

轻量级锁

  • 工作原理
    • 当偏向锁升级为轻量级锁时,线程在自己的栈帧中创建锁记录,将对象头中的 Mark Word 复制到锁记录中,然后尝试使用 CAS 操作将对象头中的 Mark Word 替换为指向锁记录的指针。如果 CAS 操作成功,线程获得锁;如果失败,表示有其他线程竞争锁,轻量级锁会膨胀为重量级锁。
  • 生效场景
    • 适用于竞争不是特别激烈的场景。在这种场景下,轻量级锁通过 CAS 操作尝试获取锁,避免了重量级锁的线程阻塞和唤醒带来的开销,能提升性能。
  • 可能面临的问题
    • 如果竞争过于激烈,CAS 操作失败频繁,轻量级锁会频繁膨胀为重量级锁,导致性能下降。而且 CAS 操作本身也有一定的开销,如果操作过于频繁,也会影响性能。