面试题:Java 的 synchronized 是怎么实现的?

synchronized 是 Java 中用于实现线程同步的关键字,它可以用来修饰方法或代码块,确保同一时间只有一个线程可以执行被修饰的代码。synchronized 的实现主要依赖于 Java 对象头中的 监视器锁(Monitor)

1. 对象头与监视器锁

在 Java 中,每个对象都有一个对象头,对象头中包含了与锁相关的信息。synchronized 的实现依赖于对象头中的 Mark Word,它存储了对象的哈希码、分代年龄、锁状态等信息。

2. 锁的状态

Java 中的锁有几种不同的状态,主要包括:

  • 无锁状态:对象没有被任何线程锁定。
  • 偏向锁:为了减少同一线程多次获取锁的开销,JVM 会偏向于第一个获取锁的线程。
  • 轻量级锁:当多个线程竞争锁时,JVM 会尝试使用轻量级锁来避免线程阻塞。
  • 重量级锁:当竞争激烈时,JVM 会将锁升级为重量级锁,此时线程会进入阻塞状态,等待锁的释放。

3. 锁的升级过程

synchronized 的锁会根据竞争情况逐步升级:

  1. 偏向锁:当第一个线程获取锁时,JVM 会将锁标记为偏向锁,并记录线程 ID。
  2. 轻量级锁:当有其他线程尝试获取锁时,偏向锁会升级为轻量级锁,JVM 会使用 CAS(Compare-And-Swap)操作来尝试获取锁。
  3. 重量级锁:如果轻量级锁竞争失败,锁会升级为重量级锁,此时线程会进入阻塞状态,等待锁的释放。

4. 实现细节

  • 修饰实例方法:锁是当前实例对象。
  • 修饰静态方法:锁是当前类的 Class 对象。
  • 修饰代码块:锁是括号中指定的对象。

5. 示例代码

public class SynchronizedExample {
    private int count = 0;

    // 修饰实例方法
    public synchronized void increment() {
        count++;
    }

    // 修饰代码块
    public void decrement() {
        synchronized (this) {
            count--;
        }
    }
}

6. 性能考虑

synchronized 是 Java 中最基本的同步机制,但在高并发场景下,可能会导致性能瓶颈。因此,Java 还提供了 java.util.concurrent 包中的更高级的并发工具,如 ReentrantLockReadWriteLock 等,以满足更复杂的并发需求。

总结

synchronized 通过对象头中的监视器锁来实现线程同步,锁的状态会根据竞争情况从偏向锁逐步升级到重量级锁。虽然 synchronized 使用简单,但在高并发场景下可能需要考虑更高效的并发控制机制。

THE END
点赞13 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容