仅供参考
对比表
|
锁类型 |
是否可重入 |
是否公平 |
是否支持超时/中断 |
读写分离 |
适用场景 |
|
synchronized |
是 |
否(JVM 优化后近似公平) |
否 |
否 |
简单同步 |
|
ReentrantLock |
是 |
可选 |
是 |
否 |
高级控制、公平性 |
|
ReentrantReadWriteLock |
是 |
可选 |
是 |
是 |
读多写少 |
|
StampedLock |
否 |
否 |
是(部分) |
是(含乐观读) |
高性能读多写少 |
|
原子类(CAS) |
— |
— |
— |
— |
无锁并发更新(计数器等) |
一、内置锁(Intrinsic Lock / Monitor Lock)
1. synchronized 关键字
- 原理:基于 JVM 的 monitor(监视器)机制。
- 作用范围:
- 方法级别(实例方法、静态方法)
- 代码块(指定对象作为锁)
java
编辑
public synchronized void method() { ... } // 锁当前对象(this)
public static synchronized void staticMethod() { ... } // 锁类对象(Class)
synchronized (lockObject) { ... } // 显式指定锁对象
✅ 使用场景:
- 简单的线程安全需求。
- 不需要高级功能(如超时、可中断、公平性等)。
- 性能要求不高但追求代码简洁和可靠性。
❌ 缺点:
- 不支持尝试获取锁(tryLock)、超时、中断。
- 无法实现读写分离(即不能区分读/写操作)。
- 锁粒度较粗,容易造成性能瓶颈。
二、显式锁(Explicit Lock)
来自 java.util.concurrent.locks 包,主要接口为 Lock。
2.1 ReentrantLock(可重入锁)
- 特点:
- 可重入(同一线程可多次获取同一把锁)。
- 支持公平/非公平模式(默认非公平)。
- 支持
tryLock()、lockInterruptibly()、tryLock(timeout)。 - 必须手动
unlock()(通常在finally块中释放)。
java
编辑
ReentrantLock lock = new ReentrantLock(true); // true 表示公平锁
lock.lock();
try {
// 临界区
} finally {
lock.unlock();
}
✅ 使用场景:
- 需要更灵活的锁控制(如超时、中断响应)。
- 高并发下需要优化锁竞争(例如配合 Condition 实现生产者-消费者模型)。
- 需要公平调度(如防止线程饥饿)。
❌ 注意:
- 容易忘记释放锁,导致死锁或资源泄漏。
- 性能略低于
synchronized(JVM 对synchronized有大量优化)。
三、读写锁(Read-Write Lock)
3.1 ReentrantReadWriteLock
- 特点:
- 分为读锁(共享)和写锁(独占)。
- 多个线程可同时持有读锁;但写锁是互斥的。
- 读-读不互斥,读-写、写-写互斥。
java
编辑
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
Lock readLock = rwLock.readLock();
Lock writeLock = rwLock.writeLock();
// 读操作
readLock.lock();
try { /* 读 */ } finally { readLock.unlock(); }
// 写操作
writeLock.lock();
try { /* 写 */ } finally { writeLock.unlock(); }
✅ 使用场景:
- 读多写少的场景(如缓存、配置管理)。
- 需要提高并发读性能。
❌ 注意:
- 写线程可能“饥饿”(尤其在高并发读时),可通过公平策略缓解。
- 不支持锁升级(不能在持有读锁时直接获取写锁)。
四、乐观锁 vs 悲观锁(思想层面)
虽然不是具体类,但在 Java 并发中广泛应用:
4.1 悲观锁(Pessimistic Locking)
- 假设会发生冲突,总是加锁。
- 如:
synchronized、ReentrantLock。
4.2 乐观锁(Optimistic Locking)
- 假设不会冲突,只在提交时检查是否被修改。
- 典型实现:CAS(Compare-And-Swap) + 版本号/时间戳。
应用:
AtomicInteger、AtomicReference等原子类。StampedLock(见下文)也支持乐观读。
五、StampedLock(Java 8 引入)
- 特点:
- 支持三种模式:写锁、悲观读锁、乐观读。
- 乐观读不加锁,通过 stamp 验证数据是否被修改。
- 性能优于
ReentrantReadWriteLock(尤其在读多写少且写不频繁时)。
java
编辑
StampedLock sl = new StampedLock();
long stamp = sl.tryOptimisticRead();
// 执行读操作
if (!sl.validate(stamp)) {
// 乐观读失败,升级为悲观读
stamp = sl.readLock();
try {
// 重新读
} finally {
sl.unlockRead(stamp);
}
}
✅ 使用场景:
- 极高并发读、低频写。
- 对性能极度敏感的系统(如高性能缓存、计数器)。
❌ 注意:
- 不可重入。
- 不支持条件变量(Condition)。
- 不能序列化。

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



