Java中synchronized锁的升级过程是为了在不同竞争强度下优化性能,分为四个阶段,按以下顺序逐步升级:
1. 无锁状态(初始阶段)
场景:对象刚创建,未被任何线程加锁。
特点:无任何同步开销,自由访问。
2. 偏向锁(单人专用模式)
触发条件:第一个线程访问同步块。
原理:
JVM在对象头记录线程ID,后续同一线程进入同步块时无需任何操作(类似“贴标签”)。
适用场景:始终只有一个线程使用锁(如单线程初始化)。
优势:几乎零开销。
升级条件:发现第二个线程尝试获取锁。
3. 轻量级锁(礼貌排队模式)
触发条件:多个线程轻度竞争(交替执行,未同时抢锁)。
原理:
线程通过自旋(循环尝试)等待锁,避免直接挂起。
对象头改为指向线程栈中的锁记录(类似“拿号排队”)。
优势:减少线程切换开销。
升级条件:自旋超过一定次数(默认自适应,通常10次左右)或多个线程持续竞争。
4. 重量级锁(强制管制模式)
触发条件:高并发竞争(多个线程同时抢锁)。
原理:
未抢到锁的线程会被操作系统挂起(进入阻塞队列),等待唤醒。
对象头指向互斥量(Mutex),由操作系统管理。
优势:避免CPU空转,适合长时间竞争。
代价:线程切换开销大,响应速度降低。
升级流程:
无锁 → [第一个线程进入] → 偏向锁 → [第二个线程竞争] → 轻量级锁 → [自旋失败/多线程争抢] → 重量级锁
5. 通俗类比
偏向锁:公司门禁卡绑定你的工号,你刷卡直接进,别人没卡不能用。
轻量级锁:临时访客需在前台登记排队,等一小会儿就能进。
重量级锁:高峰期访客太多,前台直接发号让大家去休息区等叫号。
6. 为何要升级?
无竞争时:偏向锁零开销。
轻度竞争:轻量级锁用自旋避免线程挂起。
重度竞争:重量级锁挂起线程,防止CPU空转浪费资源。
7. 注意事项
不可逆升级:一旦升级为重量级锁,无法降级。
偏向锁延迟:JVM默认程序启动初期(约4秒)不启用偏向锁,避免初始化时的竞争误判。
锁消除/锁粗化:JVM还会通过其他优化(如消除不必要的锁或合并多个锁)进一步提升性能。
总结:锁升级是JVM在安全与性能间的智能权衡,开发者只需写synchronized,底层自动适配最佳锁策略!
0条评论
点击登录参与评论