外观
锁的分类方式是什么
⭐ 题目日期:
美团 - 2024/12/23
📝 题解:
在并发编程中,锁的分类可以从多个维度进行划分,不同分类方式反映了锁的特性和适用场景。以下是常见的锁分类方式及其详细说明:
1. 按锁的获取策略(是否阻塞线程)
锁类型 | 特点 | 适用场景 | 示例 |
---|---|---|---|
阻塞锁 | 线程获取锁失败时,进入阻塞状态(释放CPU),等待唤醒。 | 锁竞争激烈或等待时间较长的情况。 | synchronized 、ReentrantLock |
自旋锁 | 线程通过循环(自旋)不断尝试获取锁,不释放CPU。 | 锁竞争不激烈且等待时间短的场景。 | AtomicInteger 的CAS操作 |
适应性自旋锁 | 自旋次数根据历史竞争情况动态调整,结合阻塞和自旋的优点。 | 对锁竞争情况不确定的优化场景。 | JVM对synchronized 的优化 |
2. 按锁的公平性(获取顺序)
锁类型 | 特点 | 适用场景 | 示例 |
---|---|---|---|
公平锁 | 严格按照线程请求锁的顺序分配锁(先到先得)。 | 需要避免线程饥饿的严格顺序场景。 | new ReentrantLock(true) |
非公平锁 | 允许线程插队获取锁,可能导致某些线程长时间等待。 | 高吞吐量优先的场景(默认选择)。 | new ReentrantLock(false) |
3. 按锁的共享性(资源访问权限)
锁类型 | 特点 | 适用场景 | 示例 |
---|---|---|---|
排他锁(写锁) | 同一时刻仅允许一个线程持有锁,其他线程无法访问共享资源。 | 写操作需要独占资源的场景。 | ReentrantLock 、synchronized |
共享锁(读锁) | 允许多个线程同时持有锁,共享资源(如只读操作)。 | 读多写少的场景(读写分离)。 | ReentrantReadWriteLock.ReadLock |
4. 按锁的实现机制(对并发的假设)
锁类型 | 特点 | 适用场景 | 示例 |
---|---|---|---|
悲观锁 | 认为并发冲突概率高,操作前先加锁(阻塞其他线程)。 | 写操作频繁或竞争激烈的场景。 | synchronized 、数据库行锁 |
乐观锁 | 假设冲突概率低,操作时无锁,提交时检测冲突(如CAS或版本号)。 | 读多写少且冲突较少的场景。 | AtomicInteger 、数据库版本号机制 |
5. 按锁的可重入性
锁类型 | 特点 | 适用场景 | 示例 |
---|---|---|---|
可重入锁 | 同一线程可多次获取同一把锁(避免死锁)。 | 递归调用或嵌套同步代码块。 | ReentrantLock 、synchronized |
不可重入锁 | 同一线程重复获取同一锁会导致死锁。 | 特殊场景需限制重复获取锁的行为。 | 简单自定义锁(需手动实现) |
6. 按锁的优化状态(针对JVM的synchronized
)
锁类型 | 特点 | 适用场景 |
---|---|---|
偏向锁 | 无竞争时,锁偏向第一个获取它的线程,无需同步操作。 | 单线程重复访问同步代码块的优化。 |
轻量级锁 | 通过CAS操作竞争锁,避免线程阻塞(自旋)。 | 低竞争且同步代码块执行快的场景。 |
重量级锁 | 竞争激烈时,锁升级为操作系统级互斥量(Mutex),线程阻塞。 | 高竞争或长时间持有锁的场景。 |
7. 按锁的粒度(并发控制范围)
锁类型 | 特点 | 示例 |
---|---|---|
粗粒度锁 | 锁住大量资源或整个数据结构,简单但并发度低。 | 对整个HashMap 加锁。 |
细粒度锁 | 锁住少量资源(如单个数据节点),提高并发度但实现复杂。 | ConcurrentHashMap 的分段锁。 |
8. 按锁的应用场景(分布式系统)
锁类型 | 特点 | 实现方式 |
---|---|---|
分布式锁 | 跨JVM或跨机器的锁,确保全局唯一性。 | 基于Redis、ZooKeeper或数据库实现。 |
9. 其他分类方式
分类维度 | 锁类型 | 特点 |
---|---|---|
是否可中断 | 可中断锁 | 等待锁的线程可被中断(如lockInterruptibly() )。 |
锁的持有者 | 显式锁(如Lock 接口) | 需手动加锁/解锁,灵活性高。 |
隐式锁(如synchronized ) | 自动加锁/解锁,语法简单但功能有限。 |
总结
- 选择锁的准则:根据并发场景(竞争强度、读写比例、性能需求)选择合适的锁类型。
- 优化方向:减少锁粒度(如分段锁)、避免长时间持有锁(如乐观锁)、优先使用高层并发工具(如
java.util.concurrent
包)。 - 经典组合:
- 读多写少:
ReentrantReadWriteLock
+ 乐观锁。 - 高并发写入:
ConcurrentHashMap
(分段锁)或StampedLock
。 - 分布式环境:Redis RedLock或ZooKeeper分布式锁。
- 读多写少: