Skip to content

锁的分类方式是什么

约 1138 字大约 4 分钟

多线程与并发美团

2025-03-26

⭐ 题目日期:

美团 - 2024/12/23

📝 题解:

在并发编程中,锁的分类可以从多个维度进行划分,不同分类方式反映了锁的特性和适用场景。以下是常见的锁分类方式及其详细说明:


1. 按锁的获取策略(是否阻塞线程)

锁类型特点适用场景示例
阻塞锁线程获取锁失败时,进入阻塞状态(释放CPU),等待唤醒。锁竞争激烈或等待时间较长的情况。synchronizedReentrantLock
自旋锁线程通过循环(自旋)不断尝试获取锁,不释放CPU。锁竞争不激烈且等待时间短的场景。AtomicInteger的CAS操作
适应性自旋锁自旋次数根据历史竞争情况动态调整,结合阻塞和自旋的优点。对锁竞争情况不确定的优化场景。JVM对synchronized的优化

2. 按锁的公平性(获取顺序)

锁类型特点适用场景示例
公平锁严格按照线程请求锁的顺序分配锁(先到先得)。需要避免线程饥饿的严格顺序场景。new ReentrantLock(true)
非公平锁允许线程插队获取锁,可能导致某些线程长时间等待。高吞吐量优先的场景(默认选择)。new ReentrantLock(false)

3. 按锁的共享性(资源访问权限)

锁类型特点适用场景示例
排他锁(写锁)同一时刻仅允许一个线程持有锁,其他线程无法访问共享资源。写操作需要独占资源的场景。ReentrantLocksynchronized
共享锁(读锁)允许多个线程同时持有锁,共享资源(如只读操作)。读多写少的场景(读写分离)。ReentrantReadWriteLock.ReadLock

4. 按锁的实现机制(对并发的假设)

锁类型特点适用场景示例
悲观锁认为并发冲突概率高,操作前先加锁(阻塞其他线程)。写操作频繁或竞争激烈的场景。synchronized、数据库行锁
乐观锁假设冲突概率低,操作时无锁,提交时检测冲突(如CAS或版本号)。读多写少且冲突较少的场景。AtomicInteger、数据库版本号机制

5. 按锁的可重入性

锁类型特点适用场景示例
可重入锁同一线程可多次获取同一把锁(避免死锁)。递归调用或嵌套同步代码块。ReentrantLocksynchronized
不可重入锁同一线程重复获取同一锁会导致死锁。特殊场景需限制重复获取锁的行为。简单自定义锁(需手动实现)

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分布式锁。