---
### 一、设计目标的差异
| **锁类型** | **核心目标** | **适用场景** |
|------------|-----------------------------------------------------------------------------|-----------------------------------------------------------------------------|
| **偏向锁** | **消除无竞争场景下的同步开销**,通过记录首次获得锁的线程 ID,后续无需任何同步操作 | 单线程重复访问同步代码(如工具类单例初始化) |
| **轻量级锁** | **减少轻量竞争场景的互斥量开销**,通过 CAS 自旋避免线程挂起 | 多线程交替访问同步块(如生产者-消费者模型中交替执行) |
**关键区别**:
偏向锁直接消除同步操作(包括 CAS),而轻量级锁仍需通过 CAS 操作获取锁,但避免了操作系统级线程阻塞。
---
### 二、加锁机制的对比
1. **偏向锁的加锁流程**
• **初始化**:首次获取锁时,通过 CAS 将线程 ID 写入对象头的 Mark Word
• **后续访问**:直接检查线程 ID 是否匹配,无任何同步操作
• **示例**:若线程 A 第一次获取锁后,后续每次进入同步块时仅需验证线程 ID 即可
2. **轻量级锁的加锁流程**
• **栈帧分配**:每次进入同步块时,在线程栈中创建锁记录(Lock Record),拷贝 Mark Word
• **CAS 竞争**:尝试将对象头指针指向锁记录,若失败则自旋重试(默认 10 次)
• **示例**:线程 A 和线程 B 交替执行同步块时,通过 CAS 交替更新锁记录指针
---
### 三、竞争处理方式的区别
| **竞争场景** | **偏向锁的响应** | **轻量级锁的响应** |
|-------------------------|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------|
| **首次出现竞争** | 撤销偏向锁,升级为轻量级锁(需暂停原持有偏向锁的线程) | 自旋尝试重新 CAS,失败则膨胀为重量级锁 |
| **持续竞争** | 直接升级为重量级锁(无中间状态) | 自旋失败后升级为重量级锁,线程进入阻塞队列 |
**典型场景**:
• 若线程 A 持有偏向锁时,线程 B 尝试获取锁 → 触发偏向锁撤销,升级为轻量级锁
• 若线程 A 和 B 同时竞争轻量级锁 → 自旋失败后膨胀为重量级锁
---
### 四、性能与适用性权衡
| **维度** | **偏向锁** | **轻量级锁** |
|------------------|---------------------------------------------------------------------------|---------------------------------------------------------------------------|
| **无竞争开销** | 零开销(仅首次 CAS) | 每次进入同步块需 CAS 操作 |
| **竞争开销** | 高(需暂停线程 + 撤销操作) | 中等(自旋消耗 CPU,但避免线程切换) |
| **适用性限制** | 仅适合单线程独占场景,多线程访问时需禁用(-XX:-UseBiasedLocking) | 适合短时间交替竞争场景,长时间竞争会退化为重量级锁 |
---
### 五、线程竞争时的锁状态变化
当 **两个线程同时竞争锁** 时:
1. **偏向锁**:立即失效 → 升级为轻量级锁 → 若仍存在竞争则进一步膨胀为重量级锁
2. **轻量级锁**:自旋重试失败 → 直接膨胀为重量级锁
**结论**:
两者在存在竞争时均会失效,最终依赖重量级锁实现同步,但轻量级锁通过自旋减少了短时间竞争的开销。
---
### 总结
| **核心差异** | **偏向锁** | **轻量级锁** |
|--------------------|------------------------------------|------------------------------------|
| **竞争容忍度** | 零容忍(任何竞争都会失效) | 容忍短暂交替竞争 |
| **性能优势场景** | 单线程独占同步块 | 多线程交替访问同步块 |
| **实现复杂度** | 高(需处理撤销逻辑) | 中(依赖 CAS 自旋) |
**选择建议**:
• 若代码块 **仅被单线程重复访问**(如工具类初始化),启用偏向锁可最大化性能
• 若存在 **短时间交替竞争**(如任务队列交替执行),轻量级锁更优
• 高竞争场景下两者均需禁用,直接使用 `ConcurrentHashMap` 等并发容器替代同步块
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传