ReentrantLock原理
外观
ReentrantLock原理[编辑 | 编辑源代码]
ReentrantLock是Java并发包(`java.util.concurrent.locks`)中提供的可重入互斥锁实现,相比`synchronized`关键字,它提供了更灵活的锁控制能力,支持公平性选择、可中断的锁获取、超时机制等高级特性。
核心特性[编辑 | 编辑源代码]
- 可重入性:线程可以重复获取已持有的锁(通过计数器实现)
- 公平性选择:支持公平锁(按等待顺序获取)和非公平锁(竞争获取)
- 锁中断:通过`lockInterruptibly()`响应中断
- 条件变量:通过`Condition`实现精细化的线程通信
底层实现原理[编辑 | 编辑源代码]
同步器(AQS)基础[编辑 | 编辑源代码]
ReentrantLock基于AbstractQueuedSynchronizer(AQS)框架实现,其核心是通过一个volatile整型变量`state`表示锁状态:
- :锁未被占用
- :锁被占用,数值表示重入次数
获取锁流程(非公平模式)[编辑 | 编辑源代码]
1. 尝试通过CAS修改state 2. 成功则设置独占线程为当前线程 3. 失败则进入AQS队列等待
释放锁流程[编辑 | 编辑源代码]
1. 减少重入计数器 2. 当state归零时:
* 清除独占线程标记 * 唤醒队列中的等待线程
代码示例[编辑 | 编辑源代码]
基础用法[编辑 | 编辑源代码]
import java.util.concurrent.locks.ReentrantLock;
public class Counter {
private final ReentrantLock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock(); // 阻塞直到获取锁
try {
count++;
System.out.println("Count: " + count);
} finally {
lock.unlock(); // 必须手动释放
}
}
}
公平锁示例[编辑 | 编辑源代码]
ReentrantLock fairLock = new ReentrantLock(true); // 公平锁
public void accessResource() {
fairLock.lock();
try {
// 临界区代码
} finally {
fairLock.unlock();
}
}
与synchronized对比[编辑 | 编辑源代码]
特性 | ReentrantLock | synchronized |
---|---|---|
实现方式 | API级实现 | JVM内置实现 |
锁获取方式 | 可非阻塞尝试(tryLock) | 仅阻塞获取 |
公平性 | 可配置 | 非公平 |
条件变量 | 支持多个Condition | 单一等待队列 |
锁释放 | 必须显式调用unlock() | 自动释放 |
高级特性[编辑 | 编辑源代码]
锁中断[编辑 | 编辑源代码]
public void performTaskWithTimeout() throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
if (lock.tryLock(1, TimeUnit.SECONDS)) { // 超时等待
try {
// 临界区
} finally {
lock.unlock();
}
} else {
System.out.println("获取锁超时");
}
}
条件变量[编辑 | 编辑源代码]
class BoundedBuffer {
final ReentrantLock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
void put(Object x) throws InterruptedException {
lock.lock();
try {
while (/* 缓冲区满 */) {
notFull.await(); // 释放锁并等待
}
// 放入数据
notEmpty.signal(); // 唤醒消费者
} finally {
lock.unlock();
}
}
}
性能考量[编辑 | 编辑源代码]
- 非公平锁(默认)通常吞吐量更高,但可能导致线程饥饿
- 公平锁保证顺序性,但增加上下文切换开销
- 在激烈竞争场景下,ReentrantLock性能可能优于synchronized
常见问题[编辑 | 编辑源代码]
实际应用案例[编辑 | 编辑源代码]
电商库存扣减系统:
- 使用ReentrantLock保护共享库存数据
- 通过tryLock实现超时控制,避免系统雪崩
- 使用Condition实现库存不足时的等待/通知机制
页面模块:Message box/ambox.css没有内容。
不当使用可能导致:
|
总结[编辑 | 编辑源代码]
ReentrantLock提供了比synchronized更精细的锁控制,适合需要高级特性的并发场景。理解其AQS实现原理有助于正确使用和性能调优。在简单场景下,仍推荐优先使用synchronized。