Java 轻量级锁面试题

1. 什么是轻量级锁?

轻量级锁是一种用于对线程访问同步块的优化,它的特点是在访问同步块之前,先将对象头中的标记位设为轻量级锁,并将锁的持有线程ID记录在对象头中。

2. 轻量级锁的工作过程是怎样的?

当一个线程尝试获取一个轻量级锁时,JVM会先在当前线程的栈中创建一个名为Lock Record的空间,并将对象头中的Mark Word拷贝到Lock Record的Displaced Mark Word中。然后,使用CAS操作尝试将对象头的Mark Word更新为指向Lock Record的指针。如果成功,则表示该线程获得了轻量级锁。

3. 轻量级锁的利弊是什么?

轻量级锁的优势在于无竞争情况下能够通过CAS操作成功获取锁,而无需进行线程切换和调度。但如果发生了锁竞争,轻量级锁会膨胀为重量级锁,这时会引入线程切换和调度的开销。

4. 轻量级锁如何升级为重量级锁?

当轻量级锁遇到锁竞争时,即有其他线程尝试获取同一把锁时,轻量级锁会膨胀为重量级锁。对象头的Mark Word改为指向重量级锁Monitor的指针,并把获取失败的线程放入一个队列中进行阻塞。

5. 轻量级锁和偏向锁有什么区别?

偏向锁是当一个线程获取了锁之后,锁就偏向于该线程,减少锁的竞争开销。而轻量级锁是在没有竞争的情况下,通过CAS操作来避免使用操作系统互斥量,减少性能损耗。

6. 轻量级锁的适用场景是什么?

轻量级锁适用于没有锁竞争或竞争较少的场景,这样可以避免重量级锁带来的性能开销。

7. 轻量级锁如何实现锁重入?

在轻量级锁状态下,如果当前线程再次请求同一个锁,JVM会检查对象头的Mark Word是否指向当前线程的Lock Record。如果是,则增加重入次数,而不是进行CAS操作。

8. 轻量级锁的获取流程是怎样的?

轻量级锁的获取流程包括:检查对象是否是无锁状态、在栈中建立Lock Record、尝试通过CAS操作将对象头的Mark Word更新为指向Lock Record的指针。

9. 轻量级锁的释放流程是怎样的?

轻量级锁的释放流程包括:检查是否有其他线程等待获取锁、通过CAS操作将对象头的Mark Word恢复为无锁状态。如果CAS操作失败,则需要调用slow_exit方法释放锁。

10. 轻量级锁和重量级锁的性能对比如何?

轻量级锁在无竞争的情况下性能优于重量级锁,但在有竞争的情况下,由于锁膨胀和线程阻塞,性能可能不如重量级锁。

11. 轻量级锁的CAS操作失败后会发生什么?

如果CAS操作失败,表示锁对象不是无锁状态,这时候JVM会判断是否是锁重入。如果不是锁重入,则尝试将轻量级锁膨胀为重量级锁。

12. 轻量级锁的适应性自旋是什么?

适应性自旋是指当轻量级锁获取失败时,线程不会立即阻塞,而是进行一定次数的自旋,尝试再次获取锁。自旋次数根据历史统计信息动态调整。

13. 轻量级锁的锁重入是如何实现的?

轻量级锁的锁重入通过在Lock Record中记录重入次数实现。每次重入时,增加重入次数;解锁时,减少重入次数。

14. 轻量级锁的锁膨胀条件是什么?

轻量级锁的锁膨胀条件包括:锁竞争、自旋超过一定次数、线程阻塞。当这些条件满足时,轻量级锁会膨胀为重量级锁。

15. 轻量级锁和偏向锁可以同时使用吗?

不可以,偏向锁和轻量级锁是互斥的。如果一个锁已经是偏向锁,那么在另一个线程尝试获取锁时,偏向锁会先被撤销,然后升级为轻量级锁。

16. 轻量级锁的CAS操作在什么情况下会失败?

CAS操作可能因为其他线程的竞争而失败,例如另一个线程已经获取了锁或者锁已经被膨胀为重量级锁。

17. 轻量级锁的锁重入次数有限制吗?

理论上,轻量级锁的锁重入次数没有限制,但实际上受限于线程栈的大小和JVM的实现。

18. 轻量级锁的获取和释放操作是否原子性?

是的,轻量级锁的获取和释放操作是原子性的,这是通过CAS操作保证的。

19. 轻量级锁在Java中是如何实现的?

在Java中,轻量级锁是通过JVM和操作系统的原子操作实现的,主要依赖于CAS指令。

20. 轻量级锁的锁膨胀过程是怎样的?

轻量级锁的锁膨胀过程包括:撤销偏向锁、复制对象头的Mark Word、创建重量级锁的Monitor对象、将获取失败的线程放入Monitor的等待队列。