synchronized 实现原理

1. 对象头与 Mark Word

每个 Java 对象在内存中分为三部分:对象头实例数据对齐填充
对象头 是核心部分,包含以下信息:

  • Mark Word(标记字段):存储对象的哈希码、分代年龄、锁状态等。
  • Klass Pointer(类型指针):指向类的元数据(方法区中的 Class 对象)。

Mark Word 的结构(以 64 位 JVM 为例):

锁状态存储内容(64位)
无锁哈希码(25位) + 分代年龄(4位) + 偏向模式(1位,0) + 锁标志位(2位,01)
偏向锁线程ID(54位) + 时间戳(2位) + 分代年龄(4位) + 偏向模式(1位,1) + 锁标志位(01)
轻量级锁指向栈中锁记录的指针(62位) + 锁标志位(00)
重量级锁指向 Monitor 的指针(62位) + 锁标志位(10)
GC 标记空(无意义) + 锁标志位(11)

锁标志位(2位) 决定了当前锁的状态:01(无锁/偏向锁)、00(轻量级锁)、10(重量级锁)、11(GC标记)。


2. Monitor 机制

每个对象关联一个 Monitor(监视器锁),其本质是 JVM 对操作系统 Mutex Lock 的封装,用于管理线程的竞争与等待。
Monitor 的结构如下:

  • Owner:持有锁的线程。
  • EntryList:等待锁的线程队列(未获取到锁的线程在此阻塞)。
  • WaitSet:调用 wait() 后进入等待状态的线程队列。

线程获取锁的流程

  1. 线程尝试通过 CAS 操作 将 Mark Word 中的锁标志位设置为轻量级锁或偏向锁。
  2. 若竞争失败,线程进入 EntryList 等待,并升级为重量级锁(依赖操作系统 Mutex Lock)。
  3. 持有锁的线程释放锁后,唤醒 EntryList 中的线程重新竞争。

3. 锁升级过程

为提高性能,JVM 在 JDK 1.6 后引入 锁升级 机制,根据竞争情况动态调整锁状态:

  1. 无锁

    • 初始状态,未发生线程竞争。
  2. 偏向锁

    • 适用场景:单线程重复访问同一同步代码。
    • 实现:将线程ID写入 Mark Word,后续访问无需 CAS 操作。
    • 触发升级:当其他线程尝试获取锁时,撤销偏向锁,升级为轻量级锁。
  3. 轻量级锁

    • 适用场景:低并发、线程交替执行同步代码。
    • 实现:通过 CAS 自旋 尝试获取锁,避免线程阻塞。
    • 触发升级:自旋超过阈值(默认 10 次)或竞争加剧时,升级为重量级锁。
  4. 重量级锁

    • 适用场景:高并发、竞争激烈。
    • 实现:依赖操作系统 Mutex Lock,线程阻塞并进入 EntryList 等待唤醒。
    • 开销:涉及用户态到内核态的切换,性能较低。

4. 字节码层面的实现

synchronized 在字节码中通过两条指令实现同步:

  • 同步代码块
    编译后插入 monitorentermonitorexit 指令,分别对应锁的获取和释放。
    public void method() {
        synchronized (this) {  // monitorenter
            System.out.println("同步代码块");
        }                     // monitorexit
    }
    
  • 同步方法
    方法标记 ACC_SYNCHRONIZED 标志,JVM 在方法调用时隐式获取锁。
    public synchronized void increase() { 
        count++; 
    }
    

5. 其他核心特性
  1. 可重入性
    同一线程可多次获取同一把锁(通过计数器实现,避免死锁)。

  2. 排他性
    同一时刻仅一个线程能持有锁,其他线程必须等待。

  3. 锁释放
    线程执行完同步代码块或抛出异常时,JVM 自动释放锁。


总结

synchronized 的底层实现结合了 对象头标记Monitor 竞争管理锁升级优化,在保证线程安全的同时兼顾性能。其核心优势在于:

  • JVM 自动管理锁:无需手动释放,避免死锁。
  • 锁升级机制:根据竞争动态调整,减少性能开销。
  • 可重入性:支持同一线程重复获取锁。

适用场景:单例模式、简单资源同步等低竞争或需快速实现同步的场景。对于高并发复杂场景,可结合 Lock 的高级功能(如超时、公平锁)优化性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值