synchronized 是 Java 并发编程中最基础的同步机制,本文从 JVM 对象内存布局出发,深入剖析 Mark Word 的结构、monitorenter/monitorexit 字节码指令以及 Monitor 对象的底层实现,结合 Java 17 的 JOL 工具展示对象头的实际变化。

标签:Java synchronized 对象头 Monitor JVM

目录

  1. 为什么需要 synchronized

  2. Java 对象内存布局

  3. Mark Word 详解

  4. Monitor 对象原理

  5. monitorenter / monitorexit 字节码分析

  6. Java 17 实战:用 JOL 观察对象头

  7. 常见坑

  8. 面试题

  9. 总结

  10. 参考资料

1. 为什么需要 synchronized

在多线程环境下,多个线程同时访问共享资源会导致数据不一致。synchronized 关键字通过互斥锁机制保证同一时刻只有一个线程能进入临界区,从而保证线程安全。

2. Java 对象内存布局

Java 对象在内存中分为三块区域:对象头、实例数据和对齐填充-2。对象头包含 Mark Word 和 Klass Pointer 两部分。

3. Mark Word 详解

Mark Word 是对象头的核心部分,64 位 JVM 中占 8 字节。其结构随锁状态动态变化:

锁状态存储内容标志位
无锁哈希码(25bit) + 分代年龄(4bit)01
偏向锁线程ID(23bit) + Epoch(2bit) + 分代年龄01
轻量级锁指向栈中锁记录的指针00
重量级锁指向 Monitor 的指针10
GC标记空11

4. Monitor 对象原理

Monitor 是 synchronized 重量级锁的实现基础,由 C++ 的 ObjectMonitor 实现,包含 Owner、EntryList、WaitSet 等关键字段。当线程获取锁失败时,会进入 EntryList 阻塞等待。

5. monitorenter / monitorexit 字节码分析

同步代码块编译后会生成 monitorenter 和 monitorexit 指令-。同步方法则通过 ACC_SYNCHRONIZED 标志实现。

6. Java 17 实战代码

java

复制

下载

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;

public class ObjectHeaderDemo {
    private static final Object lock = new Object();

    public static void main(String[] args) throws InterruptedException {
        System.out.println("JVM: " + VM.current().details());

        System.out.println("=== 无锁状态 ===");
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());

        synchronized (lock) {
            System.out.println("=== 持有锁状态 ===");
            System.out.println(ClassLayout.parseInstance(lock).toPrintable());
        }

        System.out.println("=== 释放锁后 ===");
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());
    }
}

7. 常见坑

  • 误认为 synchronized 锁的是代码块而非对象

  • 混淆对象锁与类锁的作用范围:对象锁只锁当前实例,类锁锁整个类

  • 在方法上使用 synchronized 等同于对整个方法体加锁,粒度可能过大

8. 面试题

Q1:synchronized 锁的是什么? 锁的是对象。同步代码块锁括号中的对象,同步方法锁当前实例(this),静态同步方法锁 Class 对象。

Q2:Monitor 的 Owner 字段有什么作用? 记录当前持有锁的线程,实现可重入性的关键。

Q3:为什么说 synchronized 早期性能差? 早期 synchronized 直接依赖操作系统的 Mutex,线程竞争时立即进入内核态阻塞,上下文切换开销大-61。

9. 总结

synchronized 通过对象头中的 Mark Word 和 Monitor 对象实现线程同步。理解对象头结构是掌握锁升级的前提,也是理解 JVM 并发优化的基础。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐