Skip to Content
面试题库Juc[面试题] synchronized 的是什么?synchronized 是怎么实现的?

[面试题] synchronized 的是什么?synchronized 是怎么实现的?

📖 版块 A:知识讲解版 (温故知新)

  • 定义:synchronized 是 Java 中的关键字,是一种同步锁。它通过为代码块或方法加锁,保证同一时刻只有一个线程能执行该代码,从而解决多线程间的并发安全问题。

  • 基本用法

    1. 修饰实例方法:锁住的是当前实例对象(this)。
    2. 修饰静态方法:锁住的是当前类的 Class 对象。
    3. 修饰代码块:锁住的是括号里配置的对象。
  • 实现原理(核心)

    1. JVM 层面

      • 同步代码块:通过 monitorentermonitorexit 指令实现。
      • 方法同步:通过方法表中的 ACC_SYNCHRONIZED 标志位隐式调用。
    2. 对象头(Mark Word):Java 对象头中的 Mark Word 存储了锁的状态信息(无锁、偏向锁、轻量级锁、重量级锁)。

    3. Monitor(监视器):每个对象都关联一个 Monitor 对象。在重量级锁状态下,Monitor 内部维护了 _Owner(当前持有锁的线程)、_EntryList(等待获取锁的队列)和 _WaitSet(等待唤醒的队列)。

  • 锁升级(Java 6+ 优化)

    • 为了减少获得锁和释放锁带来的性能消耗,引入了锁升级机制:无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁。这个过程是不可逆的(通常情况下)。

🎤 版块 B:面试实战版 (高手逐字稿)

Q:synchronized 的是什么?synchronized 是怎么实现的?

💬 高手逐字稿

简单来说,synchronized 是 Java 提供的一种内置的互斥锁,用来保证原子性、可见性和有序性。

在底层实现上,我们要分两个层面来看。首先是字节码层面:如果我们同步的是代码块,编译器会生成 monitorentermonitorexit 这两个指令;如果是同步方法,则会在方法常量池里打上一个 ACC_SYNCHRONIZED 的标识,本质上它们都是去获取一个叫 Monitor(监视器) 的对象。

接着我们要深入到 JVM 的对象模型。在 HotSpot 虚拟机里,每个 Java 对象在内存中都有一个“对象头”,其中有一块区域叫 Mark Word。这个 Mark Word 是实现锁的关键,它记录了锁的状态。当锁升级到重量级锁时,Mark Word 会指向一个 ObjectMonitor 对象。这个 Monitor 内部有三个核心区域:Owner 记录当前拿锁的线程,EntryList 存放阻塞等待的线程,WaitSet 存放调用了 wait 方法的线程。

这里有个容易被忽略的细节,就是 synchronized 的性能演进。在早期的 Java 版本中,synchronized 是一上来就直接调用操作系统的底层同步机制,涉及用户态和内核态的切换,非常重。但从 Java 6 开始,引入了锁升级机制。

程序会根据竞争情况,先使用偏向锁(认为只有一个线程访问),如果没有成功,再升级为轻量级锁(通过 CAS 自旋等待),如果自旋一定次数还没拿到锁,最后才会升级为重量级锁。这种平滑过渡极大地提升了它在不同并发场景下的执行效率。

【高手自问自答】:这里可能会有一个深度问题:synchronized 是如何支持可重入的? 其实在 ObjectMonitor 对象里有一个 _recursions 计数器。当同一个线程再次获取该锁时,计数器会加 1,退出同步块时减 1。直到计数器清零,锁才会真正释放。这种设计保证了同一个线程在执行递归或嵌套同步块时,不会把自己锁死。

最后更新于:
⏱️

登录后开始阅读

当前 MVP 版本只开放邮箱密码登录注册。完成登录后即可进入面试题内容。

还没有账号?先去注册