synchronized的升级过程
synchronized 的升级过程(精简 & 好笑版)
一句话总结
synchronized 的锁,会随着竞争程度一路“升职”,但只升不降。
一、synchronized 是干嘛的?
很简单:
👉 保证同一时刻,只有一个线程能干活
👉 顺便还送你一张 happens-before 的内存可见性门票
本质上,它就是在用 对象自带的监视器锁(Monitor)。
二、锁升级路线图(主线剧情)
1 | 无锁 → 偏向锁(已退休) → 轻量级锁 → 重量级锁 |
记住一句话就够了:
竞争越激烈,锁越“重”。
三、四种锁,用一句话讲清楚
1️⃣ 无锁:世界很和平
- 没人抢,直接用
- 性能最好
- 对象头里就是普通信息
🧘:“今天没人吵架。”
2️⃣ 偏向锁:对象只爱一个线程(已退役)
- 第一次用锁的线程,被对象“记住”
- 后面再来,连 CAS 都懒得做
- Java 15+ 默认禁用,已弃用
💔:“曾经专一,现在分手。”
3️⃣ 轻量级锁:礼貌地抢
- 多线程来了,但不算多
- 用 CAS + 自旋
- 运行在 用户态(Ring 3)
- 不阻塞,先忙等一会儿
🤺:“我先转几圈看看你放不放手。”
4️⃣ 重量级锁:直接叫警察
- 竞争太激烈了
- 直接上 操作系统互斥锁
- 线程 阻塞
- 进入 内核态(Ring 0)
🚨:“别吵了,全体排队!”
四、轻量级 vs 重量级(记住这张表)
| 对比项 | 轻量级锁 | 重量级锁 |
|---|---|---|
| 运行位置 | 用户态(Ring 3) | 内核态(Ring 0) |
| 手段 | CAS + 自旋 | OS Mutex |
| 线程状态 | RUNNABLE | BLOCKED |
| 上下文切换 | ❌ | ✅ |
| 适合场景 | 低竞争 | 高竞争 |
一句话版:
抢得不狠,用轻量级;打成一团,上重量级。
五、锁升级阈值能调吗?
不能精确调。
JVM 内心戏很多,会自己判断:
- 自旋次数
- 历史竞争情况
- CPU 忙不忙
你最多只能:
1 | -XX:+DisableFatLockSpin |
意思是:
“重量级锁别自旋了,直接睡。”
六、Ring 0 / Ring 3 到底在说啥?
Ring 3(用户态)
👉 轻量级锁、自旋、CAS
👉 快,但得自己忙等Ring 0(内核态)
👉 重量级锁、线程阻塞
👉 慢,但省 CPU
🧠 JVM 的哲学:
能不进内核,就不进内核。
七、为什么要搞这么复杂?
因为现实很残酷:
- 没竞争 👉 不该付出代价
- 低竞争 👉 不该进内核
- 高竞争 👉 CPU 不能白烧
所以 JVM 选择:
让锁自己“看情况做人”。
八、终极总结(面试可用)
- synchronized 不是一上来就重量级
- 锁升级 只升不降
- 轻量级锁在 用户态
- 重量级锁进 内核态
- 偏向锁 已成历史
🎯 一句话收尾:
synchronized 的本质,就是 JVM 在性能和公平之间反复横跳。
Comments




