摘要
synchronized
是 Java 最经典的并发关键字,用于保证原子性和可见性。本文将系统介绍 synchronized
的三种使用方式,以及其在 JVM 层面的实现机制(对象头、锁升级、monitorenter/monitorexit 指令),带你从应用到原理全面理解这一核心同步工具。
正文
一、为什么需要 synchronized?
在并发编程中,多个线程同时访问共享资源可能导致:
- 数据竞争:变量更新丢失;
- 可见性问题:一个线程更新了值,另一个线程仍读取旧数据;
- 有序性问题:指令重排导致逻辑异常。
synchronized
的作用就是提供一种 互斥锁机制,保证同一时间只有一个线程能进入临界区,从而解决上述问题。
二、synchronized 的三种使用方式
1. 修饰实例方法
java
public synchronized void increment() {
count++;
}
- 锁对象:当前实例(this)。
- 适用场景:保护实例字段,避免多个线程同时修改。
2. 修饰静态方法
java
public static synchronized void staticIncrement() {
counter++;
}
- 锁对象:当前类的 Class 对象(即
Class<类名>
)。 - 适用场景:保护静态字段,避免类级别的数据竞争。
3. 修饰代码块
java
public void add() {
synchronized (lock) {
count++;
}
}
- 锁对象:显式指定的对象引用。
- 适用场景:锁粒度可控,能减少竞争范围,提高性能。
总结:
实例方法
锁住对象实例;静态方法
锁住类对象;代码块
锁住指定对象。
三、synchronized 的底层原理
synchronized
在 JVM 中是通过 对象头(Object Header)+ Monitor(监视器锁) 来实现的。
1. 对象头与 Mark Word
在 HotSpot JVM 中,每个对象头(Object Header)包含:
- Mark Word:存储锁状态、哈希码、GC 分代年龄等;
- Klass Pointer:指向类的元数据。
锁相关的核心信息都在 Mark Word 中,比如锁标志位(00、01、10、11 对应不同状态)。
2. monitorenter & monitorexit 指令
编译器在同步代码块前后插入两条字节码指令:
monitorenter
:尝试获取锁;monitorexit
:释放锁。
一个线程在执行 monitorenter
时,如果锁已被占用,就会阻塞直到获取成功。
3. 锁的升级过程(优化机制)
HotSpot 对 synchronized
进行了多种优化,避免频繁进入内核态:
- 偏向锁(Biased Lock):默认锁偏向第一个获取它的线程,后续无竞争时无需加锁操作;
- 轻量级锁(Lightweight Lock):当多个线程尝试获取锁时,利用 CAS 在用户态竞争;
- 重量级锁(Heavyweight Lock):CAS 自旋失败或冲突严重时,升级为 OS 层面的互斥锁,线程进入阻塞状态。
这种 锁升级(无锁 → 偏向锁 → 轻量级锁 → 重量级锁) 的设计,大幅提高了 synchronized
的性能。
四、synchronized 的特性
- 可重入性
同一线程可以多次获取同一个锁,不会死锁。
java
public synchronized void methodA() {
methodB(); // 同一线程可再次进入
}
public synchronized void methodB() {}
- 可见性
synchronized
内部会在 释放锁时刷新主存、获取锁时读取主存,保证线程间数据可见性。 - 互斥性
同一时刻,最多只有一个线程能进入临界区。
五、工程实践中的使用建议
- 缩小锁粒度
只在必要的临界区加锁,避免长时间持有锁,提升并发度。 - 选择合适的锁对象
- 不要随便用
String
常量或全局对象作为锁,容易引发意外竞争; - 建议使用
private final Object lock = new Object();
作为显式锁对象。
- 避免死锁
在多个锁嵌套场景下,保持一致的加锁顺序。 - 适度考虑替代方案
在高并发场景下,可以使用ReentrantLock
、StampedLock
、ReadWriteLock
等并发工具类,获得更灵活的功能(如中断、超时、公平性)。
六、总结
synchronized
是 Java 并发的基石,它通过 对象头 + Monitor 实现锁机制,并结合 偏向锁、轻量级锁、重量级锁 提升性能。
三种用法分别对应 对象锁、类锁、自定义锁对象,开发时需要注意锁粒度、锁对象选择以及死锁风险。