`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 { private final Queue 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` 性能更好)