Java面试题:Synchronized的常见考点
Java面试题:Synchronized的常见考点
synchronized
关键字是 Java 并发编程中最重要的同步机制之一,也是面试中的高频考点。理解其原理和用法对于掌握 Java 并发编程至关重要。本文将深入探讨 synchronized
的常见考点,涵盖其底层原理、用法、锁优化以及与其他并发工具的比较等方面。
一、synchronized
的底层原理
synchronized
的底层实现依赖于 Java 对象头中的 Mark Word 和 Monitor。
- Mark Word: 对象头的一部分,存储对象的哈希码、GC 分代年龄、锁状态标志等信息。在轻量级锁和偏向锁状态下,Mark Word 存储指向锁记录的指针。
- Monitor: 每个 Java 对象都关联一个 Monitor 对象,也称为管程或监视器。Monitor 由 C++ 代码实现,内部维护一个计数器和等待队列。当线程获取锁时,计数器加 1;释放锁时,计数器减 1。当计数器为 0 时,锁被释放。等待队列用于存放等待获取锁的线程。
synchronized
的锁升级过程:
-
偏向锁: 当一个线程第一次获取锁时,会尝试设置 Mark Word 中的偏向线程 ID。如果设置成功,则该线程持有偏向锁,下次获取锁时无需进行 CAS 操作。偏向锁是为了优化单线程访问的情况,减少不必要的锁竞争开销。
-
轻量级锁: 当另一个线程尝试获取锁时,偏向锁会升级为轻量级锁。轻量级锁使用 CAS 操作尝试获取锁,如果成功,则线程持有轻量级锁。轻量级锁适用于锁竞争不激烈的情况,避免了重量级锁带来的系统调用开销。
-
重量级锁: 当多个线程竞争锁时,轻量级锁会膨胀为重量级锁。重量级锁依赖于操作系统的互斥量实现,需要进行系统调用,开销较大。
二、synchronized
的用法
synchronized
关键字可以用来修饰方法或代码块。
- 修饰方法:
synchronized
修饰方法时,锁对象是当前实例对象。
java
public synchronized void method() {
// 同步代码块
}
- 修饰静态方法:
synchronized
修饰静态方法时,锁对象是当前类的 Class 对象。
java
public synchronized static void staticMethod() {
// 同步代码块
}
- 修饰代码块:
synchronized(object)
指定锁对象。
java
public void method() {
Object lock = new Object();
synchronized(lock) {
// 同步代码块
}
}
三、synchronized
的锁优化
为了提高 synchronized
的性能,JVM 对其进行了一系列优化,包括:
-
自旋锁: 当线程尝试获取锁失败时,不会立即阻塞,而是会进行几次自旋操作,尝试再次获取锁。自旋锁可以避免线程上下文切换的开销,适用于锁竞争时间较短的情况。
-
锁消除: 编译器会分析代码,如果确定锁对象不可能被其他线程访问,则会消除锁操作。
-
锁粗化: 如果一系列连续的锁操作都是针对同一个对象,编译器会将这些锁操作合并成一个更大的锁操作,减少锁获取和释放的次数。
-
逃逸分析: 如果一个对象只在方法内部使用,并且没有逃逸出方法的作用域,编译器会将其分配在栈上,而不是堆上。这样可以避免堆内存分配和垃圾回收的开销,并且可以进行锁消除优化。
四、synchronized
与其他并发工具的比较
-
synchronized
vsReentrantLock
:synchronized
是 Java 关键字,ReentrantLock
是 Java 类。synchronized
是隐式锁,ReentrantLock
是显式锁,需要手动获取和释放锁。ReentrantLock
提供了更丰富的功能,例如公平锁、可中断锁、条件变量等。- 在 Java 5 之后,
synchronized
的性能已经得到了很大的提升,与ReentrantLock
的性能差距不大。
-
synchronized
vsvolatile
:synchronized
保证原子性、可见性和有序性,volatile
只保证可见性和有序性。synchronized
用于同步代码块,volatile
用于修饰变量。volatile
比synchronized
更轻量级,但不能用于解决原子性问题。
-
synchronized
vsAtomic
类:Atomic
类提供了一系列原子操作,例如AtomicInteger
、AtomicLong
等。Atomic
类使用 CAS 操作实现原子性,性能比synchronized
更高。Atomic
类适用于简单的原子操作,synchronized
适用于复杂的同步场景。
五、synchronized
的常见面试题
-
synchronized
的底层实现原理是什么? -
synchronized
的锁升级过程是怎样的? -
synchronized
和ReentrantLock
的区别是什么? -
synchronized
和volatile
的区别是什么? -
如何避免死锁?
-
synchronized
的性能优化有哪些? -
synchronized
可重入吗?为什么? (是的,因为 Monitor 记录了持有锁的线程以及重入次数) -
synchronized
修饰静态方法和非静态方法的区别是什么? -
如何选择合适的锁机制?
-
你在项目中如何使用
synchronized
?
六、总结
synchronized
是 Java 并发编程中重要的同步机制,理解其原理和用法对于编写高质量的并发程序至关重要。本文详细介绍了 synchronized
的底层原理、用法、锁优化以及与其他并发工具的比较,希望能帮助读者更好地掌握 synchronized
的相关知识点,在面试中游刃有余。 在实际应用中,需要根据具体的场景选择合适的锁机制,并注意避免死锁等并发问题。 深入理解 Java 内存模型 (JMM) 和并发编程的最佳实践,才能写出高效、稳定的并发程序。