本文目录导读:

我将为您提供一个完整的ReentrantLock案例,展示其核心特性和典型使用场景。
基础使用案例
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockBasicDemo {
private final ReentrantLock lock = new ReentrantLock();
private int count = 0;
// 基本加锁/解锁
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock(); // 必须在finally中解锁
}
}
// 可重入性演示
public void reentrantDemo() {
lock.lock();
try {
System.out.println("第一次获取锁");
// 再次获取锁(可重入)
lock.lock();
try {
System.out.println("第二次获取锁(可重入)");
// 执行一些操作
} finally {
lock.unlock();
}
} finally {
lock.unlock();
}
}
// 尝试获取锁(非阻塞)
public boolean tryIncrement() {
if (lock.tryLock()) {
try {
count++;
return true;
} finally {
lock.unlock();
}
}
return false;
}
// 带超时的尝试获取锁
public boolean tryIncrementWithTimeout(long timeout, TimeUnit unit)
throws InterruptedException {
if (lock.tryLock(timeout, unit)) {
try {
count++;
return true;
} finally {
lock.unlock();
}
}
return false;
}
// 可中断的锁获取
public void interruptibleLock() throws InterruptedException {
lock.lockInterruptibly(); // 可中断获取锁
try {
// 执行操作
Thread.sleep(100);
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
ReentrantLockBasicDemo demo = new ReentrantLockBasicDemo();
// 测试可重入性
demo.reentrantDemo();
// 测试基本功能
System.out.println("Count: " + demo.count);
}
}
公平锁与非公平锁对比
import java.util.concurrent.locks.ReentrantLock;
public class FairnessDemo {
private final ReentrantLock fairLock = new ReentrantLock(true); // 公平锁
private final ReentrantLock unfairLock = new ReentrantLock(false); // 非公平锁
public void testFairness(ReentrantLock lock, String lockName) {
Runnable task = () -> {
for (int i = 0; i < 3; i++) {
lock.lock();
try {
System.out.println(Thread.currentThread().getName()
+ " 获取" + lockName);
Thread.sleep(50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}
};
System.out.println("\n=== " + lockName + " 测试 ===");
Thread[] threads = new Thread[5];
for (int i = 0; i < 5; i++) {
threads[i] = new Thread(task, "线程" + i);
}
for (Thread t : threads) {
t.start();
}
try {
for (Thread t : threads) {
t.join();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public static void main(String[] args) {
FairnessDemo demo = new FairnessDemo();
demo.testFairness(demo.fairLock, "公平锁");
demo.testFairness(demo.unfairLock, "非公平锁");
}
}
生产者-消费者案例
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ProducerConsumerDemo {
private final ReentrantLock lock = new ReentrantLock();
private final Condition notEmpty = lock.newCondition();
private final Condition notFull = lock.newCondition();
private final Queue<Integer> queue = new LinkedList<>();
private final int capacity = 5;
private int value = 0;
// 生产者
public void produce() {
lock.lock();
try {
// 队列已满时等待
while (queue.size() == capacity) {
System.out.println("队列已满,生产者等待...");
notFull.await();
}
value++;
queue.offer(value);
System.out.println("生产者生产: " + value + ",队列大小: " + queue.size());
// 唤醒消费者
notEmpty.signal();
Thread.sleep(100); // 模拟生产耗时
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}
// 消费者
public void consume() {
lock.lock();
try {
// 队列为空时等待
while (queue.isEmpty()) {
System.out.println("队列为空,消费者等待...");
notEmpty.await();
}
Integer item = queue.poll();
System.out.println("消费者消费: " + item + ",队列大小: " + queue.size());
// 唤醒生产者
notFull.signal();
Thread.sleep(100); // 模拟消费耗时
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
ProducerConsumerDemo demo = new ProducerConsumerDemo();
// 启动生产者线程
Thread producerThread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
demo.produce();
}
}, "生产者");
// 启动消费者线程
Thread consumerThread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
demo.consume();
}
}, "消费者");
producerThread.start();
consumerThread.start();
try {
producerThread.join();
consumerThread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("生产消费完成");
}
}
高级特性展示
import java.util.concurrent.locks.ReentrantLock;
public class AdvancedReentrantLockDemo {
private final ReentrantLock lock = new ReentrantLock();
// 锁状态查询
public void lockStateDemo() {
System.out.println("=== 锁状态查询 ===");
System.out.println("是否有线程持有锁: " + lock.isLocked());
System.out.println("是否公平锁: " + lock.isFair());
lock.lock();
try {
System.out.println("持有锁后: " + lock.isLocked());
System.out.println("持有数: " + lock.getHoldCount());
System.out.println("等待队列长度: " + lock.getQueueLength());
} finally {
lock.unlock();
}
}
// 使用wait queue查询
public void waitQueueDemo() {
lock.lock();
try {
Thread t = new Thread(() -> {
lock.lock();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
});
t.start();
Thread.sleep(100);
System.out.println("=== 等待队列信息 ===");
System.out.println("当前线程是否持有锁: " + lock.isHeldByCurrentThread());
System.out.println("是否有线程在等待: " + lock.hasQueuedThreads());
System.out.println("等待线程数: " + lock.getQueueLength());
t.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}
// 性能对比:ReentrantLock vs synchronized
public static void performanceTest() {
int iterations = 100000;
int threadCount = 10;
// synchronized 测试
Object syncLock = new Object();
long startTime = System.nanoTime();
Thread[] syncThreads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
syncThreads[i] = new Thread(() -> {
for (int j = 0; j < iterations; j++) {
synchronized (syncLock) {
// 模拟操作
}
}
});
syncThreads[i].start();
}
try {
for (Thread t : syncThreads) t.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
long syncTime = System.nanoTime() - startTime;
// ReentrantLock 测试
ReentrantLock reentrantLock = new ReentrantLock();
startTime = System.nanoTime();
Thread[] lockThreads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
lockThreads[i] = new Thread(() -> {
for (int j = 0; j < iterations; j++) {
reentrantLock.lock();
try {
// 模拟操作
} finally {
reentrantLock.unlock();
}
}
});
lockThreads[i].start();
}
try {
for (Thread t : lockThreads) t.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
long lockTime = System.nanoTime() - startTime;
System.out.println("=== 性能对比 ===");
System.out.println("Synchronized耗时: " + syncTime / 1_000_000 + "ms");
System.out.println("ReentrantLock耗时: " + lockTime / 1_000_000 + "ms");
}
public static void main(String[] args) {
AdvancedReentrantLockDemo demo = new AdvancedReentrantLockDemo();
demo.lockStateDemo();
demo.waitQueueDemo();
performanceTest();
}
}
实际业务场景案例:银行账户转账
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
public class BankAccountDemo {
// 账户类
static class Account {
private final ReentrantLock lock = new ReentrantLock();
private String accountId;
private double balance;
public Account(String accountId, double balance) {
this.accountId = accountId;
this.balance = balance;
}
public String getAccountId() {
return accountId;
}
public double getBalance() {
return balance;
}
public void debit(double amount) { // 扣款
balance -= amount;
}
public void credit(double amount) { // 存款
balance += amount;
}
public ReentrantLock getLock() {
return lock;
}
}
private final Map<String, Account> accounts = new HashMap<>();
public BankAccountDemo() {
// 初始化账户
accounts.put("A001", new Account("A001", 5000));
accounts.put("A002", new Account("A002", 3000));
accounts.put("A003", new Account("A003", 8000));
}
// 安全转账(避免死锁)
public boolean transfer(String fromId, String toId, double amount) {
Account fromAccount = accounts.get(fromId);
Account toAccount = accounts.get(toId);
// 按账户ID排序获取锁,避免死锁
Account firstLock;
Account secondLock;
if (fromId.compareTo(toId) < 0) {
firstLock = fromAccount;
secondLock = toAccount;
} else {
firstLock = toAccount;
secondLock = fromAccount;
}
firstLock.getLock().lock();
try {
secondLock.getLock().lock();
try {
// 检查余额
if (fromAccount.getBalance() >= amount) {
fromAccount.debit(amount);
toAccount.credit(amount);
System.out.println("转账成功: " + fromId + " -> " + toId
+ ",金额: " + amount);
System.out.println(" " + fromId + "余额: " + fromAccount.getBalance());
System.out.println(" " + toId + "余额: " + toAccount.getBalance());
return true;
} else {
System.out.println("转账失败: " + fromId + "余额不足");
return false;
}
} finally {
secondLock.getLock().unlock();
}
} finally {
firstLock.getLock().unlock();
}
}
public static void main(String[] args) {
BankAccountDemo bank = new BankAccountDemo();
// 模拟并发转账
Thread t1 = new Thread(() -> {
bank.transfer("A001", "A002", 1000);
});
Thread t2 = new Thread(() -> {
bank.transfer("A002", "A003", 500);
});
Thread t3 = new Thread(() -> {
bank.transfer("A003", "A001", 2000);
});
t1.start();
t2.start();
t3.start();
try {
t1.join();
t2.join();
t3.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("\n=== 最终账户状态 ===");
Map<String, Account> finalAccounts = bank.accounts;
for (Map.Entry<String, Account> entry : finalAccounts.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue().getBalance());
}
}
}
| 特性 | 说明 | 示例 |
|---|---|---|
| 可重入性 | 同一线程可以多次获取同一把锁 | reentrantDemo() |
| 可中断 | 获取锁时可以被中断 | lockInterruptibly() |
| 超时机制 | 尝试获取锁可设置超时时间 | tryLock(timeout, unit) |
| 公平性 | 可配置公平锁或非公平锁 | new ReentrantLock(true) |
| 多条件 | 支持多个Condition实现精细等待/通知 | 生产者-消费者案例 |
| 锁状态查询 | 可查询锁的状态和持有情况 | isLocked(), getHoldCount() |
注意事项
- 必须手动释放锁:在
finally块中调用unlock() - 避免死锁:多个锁时要保持一致的获取顺序
- 性能考虑:简单场景使用
synchronized,复杂场景使用ReentrantLock - 线程安全:确保所有访问共享资源的路径都使用锁保护
这些案例覆盖了ReentrantLock的主要特性和典型应用场景,您可以根据实际需求选择使用。