锁的分类全面解析

1. 按锁的特性分类

(1) 乐观锁 vs 悲观锁

类型实现方式适用场景示例
乐观锁假设无冲突,失败时重试读多写少CASAtomicInteger
悲观锁假设会冲突,先加锁写多读少synchronizedReentrantLock

关键区别

  • 乐观锁:版本号CAS机制(如数据库MVCC

  • 悲观锁:直接加锁(如synchronized


(2) 公平锁 vs 非公平锁

类型特点实现
公平锁按申请顺序分配锁ReentrantLock(true)
非公平锁允许插队,吞吐量更高(默认)synchronizedReentrantLock()

性能对比

  • 公平锁:减少饥饿,但上下文切换多

  • 非公平锁:吞吐量高约10%,但可能饥饿


(3) 可重入锁 vs 不可重入锁

类型特点示例
可重入锁同一线程可重复获取锁synchronizedReentrantLock
不可重入锁重复获取会导致死锁自定义简单锁

可重入锁实现原理

// 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状态

  • 实现synchronizedReentrantLock


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强一致,可靠性高临时顺序节点

面试回答模板

"锁可以从多个维度分类:

  1. 按特性分乐观锁(如CAS)和悲观锁(如synchronized);

  2. 按公平性分公平锁和非公平锁;

  3. 按粒度分粗粒度锁和细粒度锁(如ConcurrentHashMap分段锁);

  4. 按共享性分独占锁和共享锁(如读写锁)。
    实际选择时,需根据场景权衡性能与安全性。"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值