vault backup: 2026-11-07 16:33:44
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
`ReentrantLock` 是 Java 并发包中提供的可重入锁,比 `synchronized` 更灵活。以下是其常见用法:
|
||||
|
||||
## 1. 基础锁使用
|
||||
|
||||
```java
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class BasicUsage {
|
||||
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(); // 必须放在 finally 中确保释放锁
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. 尝试获取锁(非阻塞)
|
||||
|
||||
```java
|
||||
public class TryLockExample {
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public void tryLockMethod() {
|
||||
if (lock.tryLock()) { // 尝试获取锁,立即返回结果
|
||||
try {
|
||||
// 获取锁成功,执行临界区代码
|
||||
System.out.println("获取锁成功");
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
} else {
|
||||
// 获取锁失败,执行其他逻辑
|
||||
System.out.println("获取锁失败,执行其他操作");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3. 带超时的尝试获取锁
|
||||
|
||||
```java
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class TimeoutLockExample {
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public void timeoutLockMethod() throws InterruptedException {
|
||||
// 尝试在指定时间内获取锁
|
||||
if (lock.tryLock(1, TimeUnit.SECONDS)) {
|
||||
try {
|
||||
System.out.println("在1秒内获取到锁");
|
||||
Thread.sleep(2000); // 模拟业务操作
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
} else {
|
||||
System.out.println("获取锁超时");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 可中断的锁获取
|
||||
|
||||
```java
|
||||
public class InterruptibleLockExample {
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public void interruptibleMethod() throws InterruptedException {
|
||||
lock.lockInterruptibly(); // 可响应中断的锁获取
|
||||
try {
|
||||
// 长时间操作
|
||||
while (true) {
|
||||
// 模拟长时间任务
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 公平锁与非公平锁
|
||||
|
||||
```java
|
||||
public class FairLockExample {
|
||||
// 创建公平锁(按申请顺序获取锁)
|
||||
private final ReentrantLock fairLock = new ReentrantLock(true);
|
||||
|
||||
// 创建非公平锁(默认,性能更高)
|
||||
private final ReentrantLock unfairLock = new ReentrantLock();
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 条件变量(Condition)
|
||||
|
||||
```java
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class ConditionExample {
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
private final Condition condition = lock.newCondition();
|
||||
private boolean conditionMet = false;
|
||||
|
||||
public void awaitCondition() throws InterruptedException {
|
||||
lock.lock();
|
||||
try {
|
||||
while (!conditionMet) {
|
||||
condition.await(); // 释放锁并等待
|
||||
}
|
||||
// 条件满足,执行后续操作
|
||||
System.out.println("条件满足,继续执行");
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void signalCondition() {
|
||||
lock.lock();
|
||||
try {
|
||||
conditionMet = true;
|
||||
condition.signalAll(); // 唤醒所有等待线程
|
||||
// 或使用 condition.signal() 唤醒一个线程
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 锁的查询方法
|
||||
|
||||
```java
|
||||
public class LockStatusExample {
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public void checkLockStatus() {
|
||||
System.out.println("是否被当前线程持有: " + lock.isHeldByCurrentThread());
|
||||
System.out.println("是否被锁定: " + lock.isLocked());
|
||||
System.out.println("等待队列长度: " + lock.getQueueLength());
|
||||
System.out.println("当前线程持有锁的次数: " + lock.getHoldCount());
|
||||
|
||||
// 获取锁信息
|
||||
if (lock.isLocked()) {
|
||||
System.out.println("持有锁的线程: " +
|
||||
(lock.getOwner() != null ? lock.getOwner().getName() : "null"));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 8. 综合示例:线程安全的队列
|
||||
|
||||
```java
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class BlockingQueue<T> {
|
||||
private final Queue<T> queue = new LinkedList<>();
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
private final Condition notEmpty = lock.newCondition();
|
||||
private final Condition notFull = lock.newCondition();
|
||||
private final int capacity;
|
||||
|
||||
public BlockingQueue(int capacity) {
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
public void put(T item) throws InterruptedException {
|
||||
lock.lock();
|
||||
try {
|
||||
while (queue.size() == capacity) {
|
||||
notFull.await(); // 队列满,等待
|
||||
}
|
||||
queue.offer(item);
|
||||
notEmpty.signal(); // 唤醒等待获取的线程
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public T take() throws InterruptedException {
|
||||
lock.lock();
|
||||
try {
|
||||
while (queue.isEmpty()) {
|
||||
notEmpty.await(); // 队列空,等待
|
||||
}
|
||||
T item = queue.poll();
|
||||
notFull.signal(); // 唤醒等待放入的线程
|
||||
return item;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
lock.lock();
|
||||
try {
|
||||
return queue.size();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 9. 与 synchronized 对比
|
||||
|
||||
```java
|
||||
public class Comparison {
|
||||
// synchronized 方式
|
||||
public synchronized void syncMethod() {
|
||||
// 临界区代码
|
||||
}
|
||||
|
||||
// ReentrantLock 方式
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public void lockMethod() {
|
||||
lock.lock();
|
||||
try {
|
||||
// 临界区代码
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **始终在 finally 块中释放锁**,防止异常导致锁无法释放
|
||||
2. **不要嵌套过多 tryLock**,避免代码复杂度增加
|
||||
3. **公平锁适用于等待时间差异大的场景**,但性能较低
|
||||
4. **考虑使用 tryLock 避免死锁**
|
||||
5. **合理使用 Condition 替代 Object 的 wait/notify**
|
||||
|
||||
## 选择建议
|
||||
|
||||
- 简单同步场景:优先使用 `synchronized`
|
||||
- 需要高级功能(超时、可中断、公平锁):使用 `ReentrantLock`
|
||||
- 需要多个等待条件:使用 `Condition`
|
||||
- 性能敏感场景:测试后选择(通常 `synchronized` 性能更好)
|
||||
Reference in New Issue
Block a user