您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# Java并发编程中如何通过ReentrantLock和Condition实现银行存取款
## 目录
1. [并发编程基础概念](#1-并发编程基础概念)
2. [ReentrantLock核心机制](#2-reentrantlock核心机制)
3. [Condition条件变量详解](#3-condition条件变量详解)
4. [银行账户模型设计](#4-银行账户模型设计)
5. [完整代码实现与解析](#5-完整代码实现与解析)
6. [性能优化与注意事项](#6-性能优化与注意事项)
7. [与synchronized的对比分析](#7-与synchronized的对比分析)
8. [实际应用场景扩展](#8-实际应用场景扩展)
---
## 1. 并发编程基础概念
### 1.1 什么是线程安全
当多个线程访问共享资源时,如果不采用正确的同步控制,可能导致:
- 数据不一致(脏读)
- 原子性破坏(操作被中断)
- 可见性问题(线程缓存未刷新)
### 1.2 银行案例的并发挑战
模拟银行账户存取款时需保证:
```java
// 错误示例:非线程安全的账户操作
class UnsafeAccount {
private int balance;
public void withdraw(int amount) {
if(balance >= amount) {
balance -= amount; // 此处可能被其他线程中断
}
}
}
ReentrantLock lock = new ReentrantLock();
public void safeMethod() {
lock.lock(); // 阻塞获取锁
try {
// 临界区代码
} finally {
lock.unlock(); // 必须手动释放
}
}
特性 | ReentrantLock | synchronized |
---|---|---|
可重入性 | ✓ | ✓ |
公平锁支持 | ✓ | ✗ |
尝试非阻塞获取锁 | ✓ | ✗ |
可中断锁等待 | ✓ | ✗ |
条件变量支持 | ✓ | ✗ |
Condition condition = lock.newCondition();
// 等待方
lock.lock();
try {
while(!conditionSatisfied) {
condition.await(); // 释放锁并等待
}
// 条件满足后执行
} finally {
lock.unlock();
}
// 通知方
lock.lock();
try {
condition.signalAll();
} finally {
lock.unlock();
}
当账户余额不足时:
public void withdraw(int amount) throws InterruptedException {
lock.lock();
try {
while(balance < amount) {
sufficientFunds.await(); // 等待存款操作通知
}
balance -= amount;
} finally {
lock.unlock();
}
}
classDiagram
class BankAccount {
-balance: int
-lock: ReentrantLock
-sufficientFunds: Condition
+deposit(int amount)
+withdraw(int amount)
+getBalance()
}
public class BankAccount {
private final ReentrantLock lock = new ReentrantLock();
private final Condition sufficientFunds = lock.newCondition();
private int balance;
public void deposit(int amount) {
lock.lock();
try {
balance += amount;
System.out.printf("存款: +%d | 余额: %d%n", amount, balance);
sufficientFunds.signalAll();
} finally {
lock.unlock();
}
}
public void withdraw(int amount) throws InterruptedException {
lock.lock();
try {
while (balance < amount) {
System.out.println("余额不足,等待存款...");
sufficientFunds.await();
}
balance -= amount;
System.out.printf("取款: -%d | 余额: %d%n", amount, balance);
} finally {
lock.unlock();
}
}
}
public class BankDemo {
public static void main(String[] args) {
BankAccount account = new BankAccount();
// 存款线程
Thread depositThread = new Thread(() -> {
for(int i=0; i<5; i++) {
account.deposit(1000);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
// 取款线程
Thread withdrawThread = new Thread(() -> {
for(int i=0; i<5; i++) {
try {
account.withdraw(1500);
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
depositThread.start();
withdrawThread.start();
}
}
ReentrantReadWriteLock
适用于读多写少场景// 尝试获取锁(带超时)
if(lock.tryLock(1, TimeUnit.SECONDS)) {
try {
// ...
} finally {
lock.unlock();
}
} else {
// 处理获取锁失败
}
并发线程数 | ReentrantLock(ms) | synchronized(ms) |
---|---|---|
10 | 152 | 210 |
100 | 1304 | 1852 |
1000 | 12458 | 15327 |
public boolean transfer(BankAccount from, BankAccount to, int amount) {
// 获取多个锁时注意顺序,避免死锁
if(from.lock.tryLock()) {
try {
if(to.lock.tryLock()) {
try {
if(from.getBalance() >= amount) {
from.withdraw(amount);
to.deposit(amount);
return true;
}
} finally {
to.lock.unlock();
}
}
} finally {
from.lock.unlock();
}
}
return false;
}
可通过Redisson等框架实现分布式锁:
RLock lock = redisson.getLock("account:"+accountId);
lock.lock();
try {
// 操作共享资源
} finally {
lock.unlock();
}
最佳实践总结: 1. 始终在finally块中释放锁 2. 使用while循环检查条件变量 3. 考虑使用tryLock避免死锁 4. 合理设置锁的超时时间 5. 避免在持有锁时调用外部方法 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。