当前位置: 首页 > news >正文

Java并发编程——锁升级机制

在 Java 的并发编程世界里,锁机制是保障多线程安全的关键手段。Java SE 1.6为了减少获得锁和释放锁带来的性能消耗,引入了“偏向锁”和“轻量级锁”,在 Java SE 1.6中,锁一共有4种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状 态和重量级锁状态,这几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级,意味着偏 向锁升级成轻量级锁后不能降级成偏向锁。

无锁(No Lock)

  • 适用场景:对象未被任何线程访问,或仅被单个线程无竞争访问。

  • 对象头标记:无锁状态的对象头中,Mark Word的锁标志位为001

  • 性能特点:完全无同步操作,访问速度最快。

 偏向锁(Biased Lock)

当第一个线程访问 synchronized 修饰的代码块时,JVM 会在对象头中记录下这个线程的 ID,此时对象进入偏向锁状态。偏向锁的设计理念是,如果一个锁总是被同一个线程访问,那么为该线程省去每次获取锁的开销,直接进入同步代码块

  • 设计目标:优化单线程重复加锁的场景(如循环内的同步操作)。

  • 实现机制

    1. 对象头记录偏向线程ID(Thread ID)与时间戳(Epoch)。

    2. 线程首次获取锁时,通过CAS将线程ID写入对象头,后续可直接访问。

  • 升级触发条件

    1. 其他线程尝试获取锁时,JVM撤销偏向锁(Revoke Bias),并检查原线程是否存活。

    2. 若原线程已结束,对象可重新偏向新线程;否则升级为轻量级锁。

  • JDK 15后的变化:默认禁用偏向锁(-XX:-UseBiasedLocking),因其撤销操作在高并发场景可能引入额外开销。

轻量级锁(Lightweight Lock)

当有第二个线程尝试访问同一个 synchronized 代码块时,偏向锁就无法满足需求了,此时锁会升级为轻量级锁。轻量级锁采用 CAS(Compare - And - Swap,比较并交换)操作来尝试获取锁。

JVM 会在线程的栈帧中创建一个锁记录(Lock Record),并将对象头中的 Mark Word 复制到锁记录中。然后,线程尝试使用 CAS 将对象头中的 Mark Word 更新为指向锁记录的指针。如果更新成功,线程就获得了锁,可以进入同步代码块;如果更新失败,说明锁已经被其他线程持有,线程会进行自旋等待。自旋是指线程在一段时间内不放弃 CPU 资源,不断尝试获取锁,避免了线程上下文切换的开销。如果自旋一定次数后仍未获取到锁,轻量级锁就会升级为重量级锁。

  • 适用场景:多线程交替执行但无实际竞争(如短时并发)。

  • 实现机制

    1. 线程在栈帧中创建锁记录(Lock Record),将对象头Mark Word复制到锁记录。

    2. 通过CAS将对象头指向锁记录,若成功则获取锁;失败则自旋重试或升级锁。

  • 自旋优化:JVM采用适应性自旋(Adaptive Spinning),动态调整自旋次数。

  • 升级触发条件

    1. 自旋超过阈值(默认10次,可通过-XX:PreBlockSpin调整)。

    2. 竞争线程数超过1个,升级为重量级锁。

重量级锁(Heavyweight Lock)

当多个线程竞争激烈,轻量级锁自旋多次后仍无法获取锁时,就会升级为重量级锁。重量级锁依赖于操作系统的互斥量(Mutex)来实现,当一个线程获取到重量级锁后,其他未获取到锁的线程会被阻塞,进入内核态等待。这种方式会带来较大的性能开销,因为线程的阻塞和唤醒需要进行用户态和内核态的切换。

  • 实现原理:依赖操作系统互斥量(Mutex)和条件变量(Condition Variable)。

  • 性能影响

    1. 线程竞争时进入阻塞状态,涉及用户态到内核态的切换,开销最大。

    2. 支持公平锁与非公平锁策略,通过等待队列管理线程调度。

锁类型适用场景吞吐量延迟
无锁无竞争最高最低
偏向锁单线程重复访问
轻量级锁低竞争短时并发
重量级锁高竞争长时阻塞

锁升级机制的局限性

  1. 偏向锁的权衡

    • 虽然减少了单线程开销,但撤销操作可能导致“锁冷启动”问题。

    • JDK 15后默认禁用,开发者需评估是否手动启用。

  2. 自旋的资源消耗

    长时间自旋会占用CPU资源,需结合适应性自旋策略。
  3. 不可逆升级

    一旦升级为重量级锁,无法回退到轻量级锁。

相关文章:

  • SSE:用于流式传输的协议
  • 百度热力图数据获取,原理,处理及论文应用6
  • Java 开发者需要了解的 PDF 基础知识
  • 安全防御综合练习2 nat+智能选路
  • 串的基本操作--数据结构
  • 算法日常刷题笔记(1)
  • 【数据分享】1929-2024年全球站点的逐日降雪深度数据(Shp\Excel\免费获取)
  • vLLM专题(二):安装-CPU
  • Retrofit+OkHttp+ViewModel
  • Go入门之语言变量 常量介绍
  • MongoDB 7 分片副本集升级方案详解(上)
  • CentOS 8 配置bond
  • C# 入门简介
  • Flutter 中的数据跨层传递方案
  • Qt之线程的创建与启动
  • 【JAVA工程师从0开始学AI】,第四步:闭包与高阶函数——用Python的“魔法函数“重构Java思维
  • 深入理解同步与异步I/O:从原理到实战
  • vue 判断字符串开头是http或者https
  • 2025-2-17算法打卡
  • 使用神经网络对驾驶数据进行道路类型分类
  • 上市公司重大资产重组新规九要点:引入私募“反向挂钩”,压缩审核流程
  • 四川内江警方通报一起持刀伤人致死案:因车辆停放引起,嫌犯被抓获
  • 秦洪看盘|缩量回踩,积蓄叩关能量
  • 美将解除对叙利亚制裁,外交部:中方一贯反对非法单边制裁
  • 商务部新闻发言人就暂停17家美国实体不可靠实体清单措施答记者问
  • 广西北部湾国际港务集团副总经理潘料庭接受审查调查