Synchronized 关键字的底层实现原理

这是一个经常被问道的问题。首先记住一个分界线。Java 6 之前基于重量级锁实现,之后引入锁升级(偏向锁->轻量级锁->重量级锁)减少频繁切换上下文的开销。

Java 6 之前早期版本的Synchronized 是基于重量级锁实现的。当一个线程访问一个被Synchronized 修饰的方法或者代码块,它会获取对象的锁,这个锁是与对象相关联的,每个对象都有一个锁标记。如果另外一个对象也想要访问这个方法或者代码块,它会首先检查对象是不是已经被锁定。如果已经被锁定,这个线程就会进入阻塞状态,等待持有锁的线程释放锁。这种阻塞和唤醒线程的操作涉及到操作系统层面上的上下文的切换,开销比较大,所以称之为重量级锁。

Java 6 之后引入了偏向锁,轻量级锁概念。底层实现依赖于 JVM 的监视器锁(Monitor)机制,主要涉及对象头、Monitor 对象以及字节码指令。以下是其核心原理的详细分析:


对象头与 Mark Word

每个 Java 对象在堆内存中存储时,其对象头(Object Header)包含两部分信息:

  1. Mark Word:存储对象的哈希码、锁状态标志等。
  2. Klass Pointer:指向对象所属类的元数据。

在加锁过程中,Mark Word 是关键。根据锁状态的不同,Mark Word 会动态变化:

  • 无锁状态:存储对象的哈希码、分代年龄等。
  • 偏向锁:存储持有偏向锁的线程 ID。
  • 轻量级锁:存储指向栈中锁记录的指针。
  • 重量级锁:存储指向 Monitor 对象的指针。

Monitor 机制

Monitor 是 JVM 实现的同步机制,每个对象关联一个 Monitor。其核心结构包括:

  • Owner:记录持有锁的线程。
  • EntryList:存放阻塞等待锁的线程。
  • WaitSet:存放调用 wait() 后进入等待状态的线程。

当一个线程尝试获取锁时:

  1. 如果锁未被占用,线程成为 Owner。
  2. 如果锁被占用,线程进入 EntryList 阻塞等待。
  3. 当 Owner 释放锁时,JVM 会从 EntryList 唤醒一个线程竞争锁。

锁升级过程

JVM 对 Synchronized 的优化包括锁升级,分为以下阶段:

偏向锁
  • 场景:只有一个线程访问同步块。
  • 原理:在 Mark Word 中记录线程 ID,避免 CAS 操作。
  • 触发条件:通过 -XX:+UseBiasedLocking 开启(JDK 15 后默认禁用)。
轻量级锁
  • 场景:多线程交替执行,无竞争。
  • 原理:通过 CAS 将 Mark Word 替换为线程栈中的锁记录指针。
  • 失败处理:若 CAS 失败,说明存在竞争,升级为重量级锁。
重量级锁
  • 场景:多线程竞争激烈。
  • 原理:通过操作系统互斥量(Mutex)实现,线程阻塞并进入内核态。

字节码层面实现

通过 javap -v 反编译同步代码块,可以看到以下指令:

  • monitorenter:尝试获取锁。
  • monitorexit:释放锁(确保在异常时也能释放,编译器会生成隐式 try-finally)。

示例字节码:

public void syncMethod() {
    synchronized(this) {
        System.out.println("Hello");
    }
}

对应字节码:

aload_0          // 加载 this 引用
dup              // 复制引用
astore_1         // 存储到局部变量表
monitorenter     // 加锁
...              // 同步块代码
aload_1          // 加载锁引用
monitorexit      // 释放锁


性能优化建议

  1. 减少同步块范围,避免锁粗化。
  2. 对于高并发场景,优先考虑 java.util.concurrent 包中的工具类(如 ReentrantLock)。
  3. 避免在循环内加锁,防止不必要的锁竞争。

通过理解 Synchronized 的底层机制,可以更高效地设计线程安全程序。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值