Java 并发面试题, Java 中的 synchronized 轻量级锁是否会进行自旋?
Java 并发面试题, Java 中的 synchronized 轻量级锁是否会进行自旋?
QA
Step 1
Q:: Java 中的 synchronized 轻量级锁是否会进行自旋?
A:: 是的,在 Java 中,synchronized 轻量级锁会进行自旋。在对象头中,锁的状态有无锁、轻量级锁、重量级锁等。轻量级锁通过 CAS 操作尝试获取锁,如果失败,线程会自旋一段时间再次尝试获取锁,而不是立即进入阻塞状态。自旋的目的是为了减少线程的上下文切换,提高性能。
Step 2
Q:: 什么是自旋锁?它与互斥锁有什么区别?
A:: 自旋锁是一种在等待锁时不会立即阻塞线程,而是让线程自旋(不断循环检查锁是否可用)的方法。与互斥锁不同,互斥锁在无法获取锁时会将线程挂起(阻塞),等待锁释放后再唤醒线程。自旋锁适用于锁竞争不激烈且持有锁时间短的场景,可以减少线程上下文切换的开销。但如果锁竞争激烈或持有锁时间长,自旋锁会导致 CPU 资源浪费。
Step 3
Q:: Java 中的 synchronized 锁的实现原理是什么?
A:: 在 Java 中,synchronized 关键字通过对象监视器(Object Monitor)实现锁机制。每个对象都有一个监视器,当一个线程进入 synchronized 块或方法时,它会尝试获取对象的监视器。如果成功获取(即没有其他线程持有监视器),线程可以继续执行,否则线程会被阻塞,直到监视器被释放。JVM 中,synchronized 的实现经历了从偏向锁、轻量级锁到重量级锁的优化过程,以提高性能。
Step 4
Q:: 轻量级锁和重量级锁的区别是什么?
A:: 轻量级锁(Lightweight Locking)和重量级锁(Heavyweight Locking)的主要区别在于锁的实现机制和性能。轻量级锁使用 CAS 操作和自旋机制来尝试获取锁,适用于竞争不激烈的场景,可以减少线程上下文切换。而重量级锁在竞争激烈时会使用操作系统的 mutex 实现,导致线程挂起和唤醒,适用于锁竞争激烈的场景。轻量级锁在性能上优于重量级锁,但重量级锁更适用于高竞争的情况。
Step 5
Q:: 什么是偏向锁?它是如何工作的?
A:: 偏向锁(Biased Locking)是一种 JVM 优化技术,旨在减少无竞争情况下的锁开销。当一个线程第一次获得对象锁时,对象头会记录该线程 ID,并将锁状态设置为偏向锁。此后,如果同一线程再次请求该锁,无需进行同步操作,直接进入同步块。偏向锁适用于绝大多数情况下锁没有竞争的场景,可以极大地提高性能。但在有竞争时,偏向锁会撤销并升级为轻量级锁或重量级锁。