synchronized锁升级的锁对象和Mark Word

发布于:2025-04-12 ⋅ 阅读:(53) ⋅ 点赞:(0)

在讨论synchronized锁升级和Mark Word时,提到的"对象"通常指的是锁对象,也就是被用作synchronized同步锁的那个Java对象。

1. 什么是锁对象?

锁对象是指被用于synchronized同步代码块或方法的对象实例。例如:

// 这个lock就是锁对象
Object lock = new Object(); 

synchronized(lock) {
    // 同步代码块
}

或者:

// 这个实例对象本身就是锁对象
public synchronized void method() {
    // 同步方法
}

2. 为什么锁对象特别重要?

因为Java中的synchronized机制是通过锁对象的对象头中的Mark Word来实现的:

  • 当线程进入synchronized块时,JVM会修改锁对象的Mark Word
  • 锁状态(偏向锁、轻量级锁、重量级锁)都记录在锁对象的Mark Word中
  • 锁升级过程就是锁对象的Mark Word内容变化的过程

3. 普通对象与锁对象的区别

所有Java对象在内存中都有对象头和Mark Word,但:

  • 普通对象:Mark Word主要存储哈希码、GC分代年龄等信息
  • 锁对象:当对象被用作同步锁时,其Mark Word会被JVM特殊处理,记录锁状态和线程信息

4. 对象如何变成锁对象?

对象成为锁对象是动态的:

  1. 初始状态:任何新创建的对象都是普通对象
  2. 首次同步:当对象第一次被用于synchronized时,JVM会将其标记为锁对象
  3. 状态变化:根据线程竞争情况,锁对象的Mark Word会经历锁升级过程

5. 锁对象的生命周期示例

Object obj = new Object(); // 1. 普通对象,Mark Word存储哈希码等

synchronized(obj) { // 2. 首次同步,变为偏向锁(如果开启偏向锁)
    // ...
} 

// 多线程竞争时
new Thread(() -> {
    synchronized(obj) { // 3. 可能升级为轻量级锁或重量级锁
        // ...
    }
}).start();

6. 如何验证锁对象的变化?

可以使用JOL工具观察锁对象Mark Word的变化:

Object lock = new Object();
System.out.println("初始状态:");
System.out.println(ClassLayout.parseInstance(lock).toPrintable());

synchronized(lock) {
    System.out.println("第一次加锁:");
    System.out.println(ClassLayout.parseInstance(lock).toPrintable());
}

// 多线程竞争观察升级
new Thread(() -> {
    synchronized(lock) {
        System.out.println("竞争加锁:");
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());
    }
}).start();

7. 特殊情况

  • Class对象:每个类的Class对象也可以作为锁对象
  • 数组对象:数组也可以作为锁对象
  • 字符串常量:由于字符串驻留机制,要谨慎用作锁对象

总结

在synchronized锁升级机制中,"对象"指被用作同步锁的那个对象实例(锁对象)。锁对象的Mark Word是JVM实现锁状态记录和锁升级的核心数据结构,理解这一点对掌握Java并发机制至关重要。