写点什么

Java 锁升级机制详解

  • 2025-06-16
    福建
  • 本文字数:1509 字

    阅读完需:约 5 分钟

1. 概述


Java 的锁升级机制是 JVM 在 JDK 1.6 后引入的重要优化策略,目的是在多线程环境下平衡 线程安全 与 性能开销。通过动态调整锁的复杂度,JVM 根据竞争强度逐步升级锁的状态,避免在低竞争场景下使用高成本的重量级锁。


2. 锁类型及特点



3. 锁升级的过程


锁升级路径为:无锁 → 偏向锁 → 轻量级锁 → 重量级锁,且 不可逆(只能升级,不能降级)。


3.1 无锁 → 偏向锁


  • 触发条件:第一个线程访问同步代码块时。

  • 过程:JVM 通过 CAS 操作将对象头的 Mark Word 标记为偏向锁。记录当前线程 ID 和偏向时间戳。后续同一线程再次访问时,直接通过比对线程 ID 获取锁(无需 CAS 操作)。


3.2 偏向锁 → 轻量级锁


  • 触发条件:第二个线程尝试获取同一锁(出现竞争)。

  • 过程:偏向锁失效,JVM 撤销偏向锁(可能触发 STW,Stop-The-World)。线程通过自旋(Spin)和 CAS 操作尝试获取锁。若自旋成功,则升级为轻量级锁;否则继续自旋或升级为重量级锁。


3.3 轻量级锁 → 重量级锁


  • 触发条件:自旋次数超过阈值(默认 10 次,可通过 -XX:PreBlockSpin 调整)。多个线程同时竞争锁(如第三个线程加入竞争)。

  • 过程:JVM 将锁升级为重量级锁,对象头指向监视器(Monitor)。线程进入操作系统内核态的阻塞队列,等待调度器唤醒。未获取锁的线程通过 ObjectMonitor 等待唤醒。


4. 锁升级的优缺点


4.1 优点


  1. 减少无竞争场景的开销:偏向锁和轻量级锁避免了频繁的 CAS 和上下文切换。

  2. 动态适配竞争强度:在低竞争时保持高性能,在高竞争时保证线程安全。


4.2 缺点


  1. 偏向锁撤销开销:当其他线程竞争时,撤销偏向锁会导致 STW,影响性能。

  2. 重量级锁的高开销:在高竞争场景下,频繁的线程阻塞/唤醒会显著降低性能。


5. 锁升级的优化策略


5.1 减少锁持有时间


  • 优化方向:缩短同步代码块的执行时间,降低锁的竞争概率。

  • 示例

// 不推荐:锁持有时间过长synchronized (lock) {    // 复杂计算或 IO 操作}
// 推荐:仅在关键代码块加锁int result = doSomeComputation(); // 非同步操作synchronized (lock) { sharedVariable = result;}
复制代码


5.2 使用分段锁(Segment Locking)

  • 优化方向:将一个大锁拆分为多个小锁,减少锁的竞争范围。

  • 示例ConcurrentHashMap 使用分段锁(JDK 8 后改为 CAS + synchronized)。

5.3 禁用偏向锁

  • 适用场景:频繁切换线程的场景(如高并发服务)。

  • JVM 参数

-XX:-UseBiasedLocking  # 禁用偏向锁
复制代码


5.4 调整自旋次数

  • 适用场景:轻量级锁的自旋可能因 CPU 空闲而浪费资源。

  • JVM 参数

-XX:PreBlockSpin=5  # 设置自旋次数为 5
复制代码



6. 代码示例


public class LockUpgradeExample {    private final Object lock = new Object();
public void performTask() { synchronized (lock) { // 同步代码块 } }
public static void main(String[] args) { LockUpgradeExample example = new LockUpgradeExample(); Thread t1 = new Thread(example::performTask); Thread t2 = new Thread(example::performTask);
t1.start(); // 初始为偏向锁(t1) t2.start(); // 触发偏向锁撤销,升级为轻量级锁 }}
复制代码


7. 关键 JVM 参数



8. 总结


  • 锁升级是 JVM 自动管理的机制,开发者无需手动干预,但理解其原理有助于优化并发性能。

  • 偏向锁适合单线程场景,轻量级锁适合低竞争场景,重量级锁适合高竞争场景。

  • 锁升级不可逆,一旦升级到重量级锁,后续操作将始终使用重量级锁。


通过合理设计代码(如减少锁粒度、避免过早膨胀到重量级锁),可以最大化 Java 的并发性能。


文章转载自:java金融

原文链接:https://www.cnblogs.com/root429/p/18927414

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

还未添加个人签名 2025-04-01 加入

还未添加个人简介

评论

发布
暂无评论
Java 锁升级机制详解_Java_量贩潮汐·WholesaleTide_InfoQ写作社区