synchronized 底层原理深度详解

synchronized 是 JVM 内置的可重入、非公平互斥锁 ,底层基于对象头 MarkWord + Monitor 监视器 实现,JDK 1.6 后通过锁升级大幅优化性能,保证并发下的原子性、可见性、有序性。


二、底层实现原理(核心必答)

  1. 锁的本质:锁的是对象,不是代码

    • 修饰实例方法:锁当前对象 this
    • 修饰静态方法:锁当前类的 Class 对象
    • 修饰代码块:锁括号里指定的对象
  2. 对象头与 Monitor

    • Java 对象在堆中分为:对象头、实例数据、对齐填充。
    • MarkWord 存储:哈希码、分代年龄、锁状态、线程 ID。
    • 每个对象关联一个 Monitor(ObjectMonitor) ,由 C++ 实现,包含:
      • _owner:持有锁的线程
      • _count:重入计数
      • _EntryList:阻塞等待队列
      • _WaitSet:调用 wait () 的等待队列
  3. 字节码指令

    • 同步代码块:monitorenter 加锁、monitorexit 解锁。
    • JVM 会自动生成两个 monitorexit,保证正常 / 异常都能释放锁。
    • 同步方法:通过方法标识 ACC_SYNCHRONIZED 实现。

三、锁升级流程(JDK 1.6+ 最重要考点)

不可逆流程:无锁 → 偏向锁 → 轻量级锁 → 重量级锁

  1. 偏向锁

    • 适用:单线程反复获取锁,无竞争
    • MarkWord 记录线程 ID,后续直接进入,无同步开销
    • 一旦出现其他线程竞争,立即升级为轻量级锁
  2. 轻量级锁

    • 适用:线程交替执行,竞争时间短
    • 线程在栈帧中创建锁记录,用 CAS 尝试抢占锁
    • 竞争失败则自旋,自旋一定次数仍失败 → 升级重量级锁
  3. 重量级锁

    • 依赖操作系统 Mutex Lock 互斥量
    • 线程进入内核态阻塞,放入 EntryList
    • 开销大,但不占用 CPU

四、三大特性

  1. 可重入 同一线程可多次获取同一把锁,底层靠 _count 计数实现,避免死锁。

  2. 非公平锁线程竞争不按等待顺序,新线程可直接抢占,吞吐量高,但可能产生饥饿。

  3. 保证可见性 加锁时从主存刷新,解锁时写回主存,底层通过内存屏障实现 Happens-Before。


五、高频面试题答案

1. synchronized 保证了什么?

原子性、可见性、有序性。

2. 为什么是可重入锁?

通过 Monitor 中的 _count 计数器实现,同一线程加锁计数 + 1,解锁 - 1,为 0 才真正释放。

3. 锁升级为什么不可逆?

为了简化 JVM 实现,避免状态回退带来的复杂度和并发安全问题。

4. synchronized 和 ReentrantLock 区别?

  • synchronized:JVM 实现,自动加解锁,非公平,功能少
  • ReentrantLock:JDK 实现,手动加解锁,可公平 / 非公平,支持条件等待、超时、中断

六、精简版

synchronized 是 JVM 内置的互斥锁,底层基于对象头 MarkWordMonitor 监视器 ,通过 monitorenter/monitorexit 指令实现。JDK 1.6 后引入锁升级 :无锁→偏向锁→轻量级锁→重量级锁,用来减少高并发开销。它是可重入、非公平锁,能保证原子性、可见性、有序性。

相关推荐
小bo波10 小时前
使用Thread子类创建线程 VS 使用Runnable接口创建线程的区别
java·多线程·thread·并发编程·runnable
SamDeepThinking10 小时前
高并发场景下,CompletableFuture与ForkJoinPool该如何取舍?
java·后端·面试
张不才13 小时前
CPU 100% 了怎么办?Java 性能排障的标准化操作
java·后端
shepherd11115 小时前
吞吐量提升 10 倍:高并发大批量数据处理任务的架构演进与性能调优
java·后端·架构
plainGeekDev17 小时前
单例模式 → object 声明
android·java·kotlin
用户2986985301418 小时前
Java 实现 Word 文档文本与图片提取的方法
java·后端
SimonKing19 小时前
铁子,IntelliJ IDEA 2026.1.3来了,升不升?
java·后端·程序员
咖啡八杯1 天前
GoF设计模式——策略模式
java·后端·spring·设计模式
用户128526116022 天前
我把祖传Java项目重构后,接口响应从3s砍到了200ms,只改了这几行代码
java