vault backup: 2026-11-07 16:33:44

This commit is contained in:
cheney
2026-11-07 16:33:55 +08:00
commit 7015312702
1208 changed files with 132432 additions and 0 deletions
+258
View File
@@ -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` 性能更好)