synchronized从偏向锁到重量级锁:JVM锁升级全流程

90%的人能说出偏向锁、轻量级锁、重量级锁 ,但说不清楚为什么要升级、什么时候升级、底层怎么实现、性能差在哪


前言:一句话说清锁升级的意义

synchronized不是一上来就加重量级锁(OS互斥锁)!

JVM非常聪明,它会根据并发竞争程度,自动逐步升级锁无锁 → 偏向锁 → 轻量级锁 → 重量级锁 ,这就是锁膨胀(Lock Inflation)

目的只有一个:在并发越低的场景,锁开销越小;竞争激烈才动用重锁。


一、先搞懂:锁信息存在哪里?

所有锁状态,都存在对象头(Mark Word)里。你加锁的对象,本身就存储了:

  • 谁持有锁
  • 锁是什么状态
  • 线程ID
  • 指向锁记录的指针
  • 指向重量级锁的指针

锁升级 = Mark Word里的内容不断改写。


二、锁升级全流程

1)无锁状态(No Lock)

  • 没有线程竞争
  • 对象正常创建

Mark Word存储: 对象哈希码、分代年龄。


2)偏向锁(Biased Lock)------ 第一个线程进来

触发条件

只有一个线程反复加锁,无竞争。

JVM 做了什么

  • 锁直接偏向这个线程
  • 不在走CAS,不做任何同步操作
  • 只需要判断对象头的线程ID是否是自己

效率

几乎无开销,和不加锁差不多快。

什么时候升级?

当第二个线程尝试竞争锁时,偏向锁立刻撤销 → 升级为轻量级锁。


3)轻量级锁(Lightweight Lock)------ 有少量竞争

触发条件

多个线程交替加锁,极少同时竞争。

底层实现

  • 线程在栈帧创建Lock Record
  • CAS尝试替换对象头
  • 成功 = 加锁成功
  • 失败 = 自旋(空转)

优点

不进入内核态,不阻塞线程,速度快。

什么时候升级?

  • 自旋次数达到阈值(JVM自动控制)
  • 有线程长时间持有锁
  • 有多个线程同时竞争

升级为重量级锁


4)重量级锁(Heavyweight Lock)------ 高并发竞争

触发条件

激烈竞争、多线程同时抢锁。

底层实现

  • 操作系统内核申请互斥锁(Mutex)
  • 拿不到锁的线程进入阻塞状态(BLOCKED)
  • 线程从用户态 → 内核态(开销巨大)

缺点

开销最大、最慢、线程上下文切换重。


三、一张图看懂锁升级流程

复制代码
无锁
  ↓ (第一个线程加锁)
偏向锁 【只给一个线程用】
  ↓ (第二个线程竞争)
偏向锁撤销
  ↓
轻量级锁 【CAS + 自旋】
  ↓ (自旋失败/竞争激烈)
重量级锁 【OS 互斥锁 + 线程阻塞】

四、三种锁的核心对比

实现 原理 优点 缺点 适用场景
偏向锁 Mark Word 存线程ID 无竞争就不做同步 最快,几乎零成本 多线程竞争会撤销(开销大) 单线程反复执行同步块
轻量级锁 CAS + 自旋 不阻塞,空转重试 响应快、不挂起线程 自旋消耗CPU 低竞争、锁持有时间短
重量级锁 OS 互斥锁 阻塞线程、内核调度 不消耗CPU 线程阻塞、上下文切换 高并发、锁持有时间长

五、最关键的6个底层真相(90%人不知道)

1)偏向锁在JDK 15+默认关闭

因为高并发场景下,偏向锁撤销开销太大

JDK15以后默认直接启动到轻量级锁

2)轻量级锁的自旋不是固定次数

JDK7以后自适应自旋

  • 之前成功 → 多自旋
  • 之前失败 → 少自旋
  • 智能、自动优化

3)锁只能升级,不能降级

偏向 → 轻量 → 重量 ,一旦升级,不能退回去

4)synchronized 是可重入锁

同一线程可以反复加锁,计数器+1。

5)wait() / notify() 必须用重量级锁

只有重量级锁才支持等待/唤醒。

6)锁消除、锁粗化都是JIT优化

  • 锁消除:未逃逸对象的锁直接删掉
  • 锁粗化:把连续加锁合并成一个大锁
    这也是synchronized越来越快的原因。

六、生产实战意义

1)锁持有时间越短越好

轻量级锁自旋效率极高,锁一长,必膨胀成重量级锁。

2)高并发服务建议关闭偏向锁

复制代码
-XX:-UseBiasedLocking

避免高并发下偏向锁撤销导致性能暴跌。

3)不要让锁竞争激烈

竞争激烈 = 重量级锁 = 线程大量阻塞 = TPS暴跌。

4)局部变量、私有对象 = 锁永远不会升级

JIT直接锁消除,性能无敌。


七、总结

synchronized锁升级流程:

  1. 无锁
  2. 偏向锁:单线程无竞争,直接偏向
  3. 轻量级锁:多线程交替执行,CAS + 自旋
  4. 重量级锁:竞争激烈,OS内核互斥锁

核心思想:无竞争不加锁,少竞争用轻锁,高竞争才用重锁。


synchronized从来不是笨重的重量级锁。它是JVM精心设计的智能自适应锁理解锁升级,才算真正掌握 Java 高并发。

相关推荐
m0_716430072 小时前
CSS项目开发如何提速_应用BEM规范建立可复用的样式库
jvm·数据库·python
maqr_1102 小时前
PyTorch bfloat16 张量转 NumPy 的兼容性解决方案
jvm·数据库·python
weixin_408717772 小时前
mysql如何防止SQL注入攻击_使用预编译语句与参数化查询
jvm·数据库·python
somi72 小时前
ARM-10-SQLite3 库移植笔记
jvm·笔记·sqlite
952362 小时前
-JVM-
jvm
weixin_424999362 小时前
http-equiv属性有哪些常用值_meta模拟HTTP头汇总【详解】
jvm·数据库·python
2301_813599552 小时前
持久化存储如何适配不同浏览器?解决隐私模式下存储失败的指南
jvm·数据库·python
2501_914245932 小时前
SQL如何高效提取大表前几行:分页查询与OFFSET优化
jvm·数据库·python
LJianK12 小时前
进程、线程、多线程、异步
java·开发语言·jvm