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 的锁升级过程:

  1. 偏向锁: 当一个线程第一次获取锁时,会尝试设置 Mark Word 中的偏向线程 ID。如果设置成功,则该线程持有偏向锁,下次获取锁时无需进行 CAS 操作。偏向锁是为了优化单线程访问的情况,减少不必要的锁竞争开销。

  2. 轻量级锁: 当另一个线程尝试获取锁时,偏向锁会升级为轻量级锁。轻量级锁使用 CAS 操作尝试获取锁,如果成功,则线程持有轻量级锁。轻量级锁适用于锁竞争不激烈的情况,避免了重量级锁带来的系统调用开销。

  3. 重量级锁: 当多个线程竞争锁时,轻量级锁会膨胀为重量级锁。重量级锁依赖于操作系统的互斥量实现,需要进行系统调用,开销较大。

二、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 vs ReentrantLock:

    • synchronized 是 Java 关键字,ReentrantLock 是 Java 类。
    • synchronized 是隐式锁,ReentrantLock 是显式锁,需要手动获取和释放锁。
    • ReentrantLock 提供了更丰富的功能,例如公平锁、可中断锁、条件变量等。
    • 在 Java 5 之后,synchronized 的性能已经得到了很大的提升,与 ReentrantLock 的性能差距不大。
  • synchronized vs volatile:

    • synchronized 保证原子性、可见性和有序性,volatile 只保证可见性和有序性。
    • synchronized 用于同步代码块,volatile 用于修饰变量。
    • volatilesynchronized 更轻量级,但不能用于解决原子性问题。
  • synchronized vs Atomic 类:

    • Atomic 类提供了一系列原子操作,例如 AtomicIntegerAtomicLong 等。
    • Atomic 类使用 CAS 操作实现原子性,性能比 synchronized 更高。
    • Atomic 类适用于简单的原子操作,synchronized 适用于复杂的同步场景。

五、synchronized 的常见面试题

  1. synchronized 的底层实现原理是什么?

  2. synchronized 的锁升级过程是怎样的?

  3. synchronizedReentrantLock 的区别是什么?

  4. synchronizedvolatile 的区别是什么?

  5. 如何避免死锁?

  6. synchronized 的性能优化有哪些?

  7. synchronized 可重入吗?为什么? (是的,因为 Monitor 记录了持有锁的线程以及重入次数)

  8. synchronized 修饰静态方法和非静态方法的区别是什么?

  9. 如何选择合适的锁机制?

  10. 你在项目中如何使用 synchronized?

六、总结

synchronized 是 Java 并发编程中重要的同步机制,理解其原理和用法对于编写高质量的并发程序至关重要。本文详细介绍了 synchronized 的底层原理、用法、锁优化以及与其他并发工具的比较,希望能帮助读者更好地掌握 synchronized 的相关知识点,在面试中游刃有余。 在实际应用中,需要根据具体的场景选择合适的锁机制,并注意避免死锁等并发问题。 深入理解 Java 内存模型 (JMM) 和并发编程的最佳实践,才能写出高效、稳定的并发程序。

THE END