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

synchronized锁升级过程【AI笔记,仅供自己参考】

在 Java 中,synchronized 是一种内置的同步机制,用于保证多线程环境下代码的原子性、可见性和有序性。从 JDK 1.6 开始,为了减少锁带来的性能开销,Java 对 synchronized 做了大量优化,引入了 锁升级机制(Lock Escalation)


🔐 一、什么是锁升级?

锁升级是指 JVM 在运行时根据对象的使用情况,对对象的锁状态进行动态优化的过程。它不是“升级为更重的锁”,而是从轻量级锁逐步升级到重量级锁的过程,以在不同竞争程度下取得性能平衡。


🧱 二、锁的类型(对象头中的 Mark Word)

在 Java 中,每个对象都有一个对象头(Object Header),其中的 Mark Word 保存了对象的哈希码、GC 分代年龄、锁状态等信息。锁的升级就体现在 Mark Word 的变化上。

锁的状态分为以下几种:

锁状态描述
无锁状态(Unlocked)对象未被任何线程锁定
偏向锁(Biased Locking)只有一个线程访问同步块时使用
轻量级锁(Lightweight Locking)多个线程交替执行同步块,没有竞争
重量级锁(Inflated Lock)多个线程发生竞争,锁膨胀为 OS 层面的互斥量(Mutex)

🔁 三、锁升级流程(从无锁到重量级锁)

深色版本

无锁状态│▼
偏向锁(只有一个线程)│(有竞争)▼
轻量级锁(CAS 尝试加锁)│(竞争激烈)▼
重量级锁(阻塞线程)

1. 无锁状态

  • 初始状态,对象未被任何线程锁定。
  • Mark Word 中记录的是对象的 hash、GC 信息等。

2. 偏向锁(Biased Locking)

  • 当一个线程访问同步块并获取锁时,JVM 会将对象头中的 Mark Word 设置为该线程 ID。
  • 表示这个对象“偏向”这个线程。
  • 优点:避免了无竞争情况下的同步开销。
  • 缺点:当有其他线程尝试获取锁时,偏向锁会失效,需要撤销(Revoke)并升级为轻量级锁。

✅ 偏向锁默认是开启的(JDK 6~15),但可以通过 JVM 参数关闭:

-XX:-UseBiasedLocking

3. 轻量级锁(Lightweight Locking)

  • 多个线程交替执行同步块,没有实际竞争
  • 使用 CAS(Compare and Swap)操作尝试将对象头的 Mark Word 替换为指向线程栈中锁记录的指针。
  • 如果 CAS 成功,则获得锁;失败则说明有竞争,进入锁膨胀。

4. 重量级锁(Inflated Lock)

  • 多个线程发生竞争时,锁会膨胀为 OS 层面的互斥锁(Mutex)。
  • JVM 会把线程阻塞,并等待操作系统调度。
  • 性能开销最大,因为涉及到线程上下文切换和系统调用。

🧪 四、锁升级的触发条件

条件锁升级
第一次加锁无锁 → 偏向锁
有线程竞争(偏向锁)偏向锁 → 轻量级锁
CAS 失败(轻量级锁)轻量级锁 → 重量级锁

📈 五、锁升级的性能影响

锁类型性能开销适用场景
偏向锁✅ 最低单线程访问同步块
轻量级锁⚠️ 较低多线程交替访问
重量级锁❌ 最高多线程竞争激烈

🧪 六、代码示例演示锁升级过程

public class SynchronizedLockUpgrade {public static void main(String[] args) throws InterruptedException {Object obj = new Object();new Thread(() -> {synchronized (obj) {System.out.println("Thread 1: holding lock");printMarkWord(obj);}}, "Thread-1").start();Thread.sleep(1000); // 确保 Thread-1 执行完偏向锁new Thread(() -> {synchronized (obj) {System.out.println("Thread 2: trying to get lock");printMarkWord(obj);}}, "Thread-2").start();}// 通过 JVM 工具打印对象头(Mark Word)private static void printMarkWord(Object obj) {// 实际中使用 JOL(Java Object Layout)库查看对象头// 示例代码略}
}

⚠️ 说明:要查看对象头(Mark Word)的变化,可以使用 JOL(Java Object Layout) 工具。


🛠️ 七、优化建议

场景建议
无并发竞争启用偏向锁,减少同步开销
短期竞争使用轻量级锁
长期竞争使用重量级锁或 ReentrantLock
高并发场景考虑使用 ReentrantLock 或分段锁(如 ConcurrentHashMap
不需要同步避免使用 synchronized,使用 volatile 或原子类

📚 八、相关 JVM 参数(了解)

参数说明
-XX:+UseBiasedLocking启用偏向锁(默认开启)
-XX:BiasedLockingStartupDelay=0提前启用偏向锁
-XX:-UseBiasedLocking禁用偏向锁
-XX:+PrintCommandLineFlags查看当前 JVM 使用的参数

✅ 九、总结:synchronized 的锁升级过程

步骤锁类型触发条件
1无锁状态初始状态
2偏向锁第一次加锁(单线程)
3轻量级锁多线程交替访问(CAS)
4重量级锁线程竞争激烈(锁膨胀)

📌 十、延伸阅读

  • Java Object Layout (JOL)
  • 《深入理解 Java 虚拟机》——周志明(第3版)
  • JVM 源码分析:synchronizer.cpp 和 objectMonitor.cpp

http://www.dtcms.com/a/286180.html

相关文章:

  • Pythonday17
  • 中国1km逐月潜在蒸散发数据集 - matlab按shp批量裁剪
  • lesson17:Python函数之递归、匿名函数与变量作用域
  • 电脑装机软件一键安装管理器
  • sky-take-out项目Mybatis的使用
  • MyBatis 动态 SQL:让 SQL 语句随条件灵活变化
  • Java面试宝典:Maven
  • UE5多人MOBA+GAS 番外篇:使用ECC(UGameplayEffectExecutionCalculation)制作伤害计算的流程
  • 【Java新特性】Java 17 新特性全解析
  • 嵌入式Linux:什么是线程?
  • Docker搭建Elasticsearch和Kibana
  • 图机器学习(12)——社区检测
  • 飞牛上使用Docker方式部署LibreTV,再配合内网穿透,实现免费无广告刷剧的服务教程
  • Oracle ADG 一键自动化搭建脚本
  • 【宇树科技:未来1-3年,机器人可流水线打螺丝】
  • Go语言实战案例-模拟登录验证(用户名密码)
  • 什么是高光谱相机,它与数码相机有什么区别?
  • C#引用转换核心原理:类型视角切换
  • 弧焊机器人智能节气装置
  • Android 开机流程中的图片与动画解析
  • leetcode:冗余连接 II[并查集检查环][节点入度]
  • Android 之 audiotrack
  • 协作机器人操作与编程-PE系统示教编程和脚本讲解(直播回放)
  • 多模态大模型重构人机交互,全感官时代已来
  • PPIO × Lemon AI:一键解锁全流程自动化开发能力
  • Rust交叉编译自动化实战
  • 服务器内存满了怎么清理缓存?
  • 【DPDK】高性能网络测试工具Testpmd使用指南
  • ARINC818航空总线机载视频处理系统设计
  • 第一篇htmlcss详细讲解