1. 按锁的特性分类
(1) 乐观锁 vs 悲观锁
| 类型 | 实现方式 | 适用场景 | 示例 |
|---|---|---|---|
| 乐观锁 | 假设无冲突,失败时重试 | 读多写少 | CAS、AtomicInteger |
| 悲观锁 | 假设会冲突,先加锁 | 写多读少 | synchronized、ReentrantLock |
关键区别:
-
乐观锁:
版本号或CAS机制(如数据库MVCC) -
悲观锁:直接加锁(如
synchronized)
(2) 公平锁 vs 非公平锁
| 类型 | 特点 | 实现 |
|---|---|---|
| 公平锁 | 按申请顺序分配锁 | ReentrantLock(true) |
| 非公平锁 | 允许插队,吞吐量更高(默认) | synchronized、ReentrantLock() |
性能对比:
-
公平锁:减少饥饿,但上下文切换多
-
非公平锁:吞吐量高约10%,但可能饥饿
(3) 可重入锁 vs 不可重入锁
| 类型 | 特点 | 示例 |
|---|---|---|
| 可重入锁 | 同一线程可重复获取锁 | synchronized、ReentrantLock |
| 不可重入锁 | 重复获取会导致死锁 | 自定义简单锁 |
可重入锁实现原理:
// ReentrantLock 内部通过计数器实现重入
if (currentThread == ownerThread) {
state++; // 重入次数+1
}
2. 按锁的实现方式分类
(1) 内置锁(JVM 实现)
-
synchronized-
自动获取/释放锁
-
支持锁升级(偏向锁→轻量级锁→重量级锁)
-
(2) 显式锁(JDK 实现)
-
ReentrantLock-
需要手动
lock()/unlock() -
支持公平/非公平、可中断、超时等特性
-
-
StampedLock(Java 8+)-
乐观读锁+写锁混合模式
-
3. 按锁的粒度分类
| 类型 | 特点 | 示例 |
|---|---|---|
| 粗粒度锁 | 锁住整个资源 | 同步整个方法 |
| 细粒度锁 | 只锁部分数据 | ConcurrentHashMap分段锁 |
| 锁分段 | 将数据分片,不同片用不同锁 | ConcurrentHashMap(Java 7) |
优化趋势:
🔹 Hashtable(全局锁) → 🔹 ConcurrentHashMap(分段锁) → 🔹 CAS+synchronized(Java 8+)
4. 按线程阻塞方式分类
(1) 自旋锁
-
原理:线程循环尝试获取锁(避免上下文切换)
-
适用场景:锁竞争时间短(如
AtomicInteger) -
风险:长时间自旋浪费CPU
(2) 阻塞锁
-
原理:获取失败时线程进入
WAITING状态 -
实现:
synchronized、ReentrantLock
5. 按共享性分类
| 类型 | 特点 | 示例 |
|---|---|---|
| 独占锁 | 同一时间只有一个线程能持有 | ReentrantLock |
| 共享锁 | 多个线程可同时读取 | ReentrantReadWriteLock.ReadLock |
读写锁对比:
ReadWriteLock rwLock = new ReentrantReadWriteLock();
rwLock.readLock().lock(); // 多个线程可同时读
rwLock.writeLock().lock(); // 独占写锁
6. 特殊锁类型
(1) 偏向锁(Biased Locking)
-
优化场景:单线程重复访问同步块
-
原理:在对象头记录线程ID,避免CAS操作
(2) 轻量级锁
-
优化场景:多线程无竞争
-
原理:用CAS替换操作系统互斥锁
(3) 重量级锁
-
最终方案:通过操作系统
mutex实现 -
特点:上下文切换成本高
7. 分布式锁
| 实现方式 | 特点 | 示例 |
|---|---|---|
| 数据库 | 简单但性能差 | SELECT FOR UPDATE |
| Redis | 高性能,需处理续约问题 | SETNX+Redisson |
| Zookeeper | 强一致,可靠性高 | 临时顺序节点 |
面试回答模板
"锁可以从多个维度分类:
按特性分乐观锁(如CAS)和悲观锁(如synchronized);
按公平性分公平锁和非公平锁;
按粒度分粗粒度锁和细粒度锁(如ConcurrentHashMap分段锁);
按共享性分独占锁和共享锁(如读写锁)。
实际选择时,需根据场景权衡性能与安全性。"

被折叠的 条评论
为什么被折叠?



