温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java并发编程中如何通过ReentrantLock和Condition实现银行存取款

发布时间:2021-11-20 15:15:13 来源:亿速云 阅读:200 作者:柒染 栏目:云计算
# 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; // 此处可能被其他线程中断 } } } 

2. ReentrantLock核心机制

2.1 锁的基本使用

ReentrantLock lock = new ReentrantLock(); public void safeMethod() { lock.lock(); // 阻塞获取锁 try { // 临界区代码 } finally { lock.unlock(); // 必须手动释放 } } 

2.2 重要特性对比

特性 ReentrantLock synchronized
可重入性
公平锁支持
尝试非阻塞获取锁
可中断锁等待
条件变量支持

3. Condition条件变量详解

3.1 等待/通知机制

Condition condition = lock.newCondition(); // 等待方 lock.lock(); try { while(!conditionSatisfied) { condition.await(); // 释放锁并等待 } // 条件满足后执行 } finally { lock.unlock(); } // 通知方 lock.lock(); try { condition.signalAll(); } finally { lock.unlock(); } 

3.2 银行案例中的条件应用

当账户余额不足时:

public void withdraw(int amount) throws InterruptedException { lock.lock(); try { while(balance < amount) { sufficientFunds.await(); // 等待存款操作通知 } balance -= amount; } finally { lock.unlock(); } } 

4. 银行账户模型设计

4.1 类结构设计

classDiagram class BankAccount { -balance: int -lock: ReentrantLock -sufficientFunds: Condition +deposit(int amount) +withdraw(int amount) +getBalance() } 

4.2 线程交互流程

  1. 存款线程获取锁
  2. 修改余额后发出signalAll
  3. 取款线程被唤醒后检查条件
  4. 满足条件则执行取款

5. 完整代码实现与解析

5.1 账户实现类

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(); } } } 

5.2 线程测试类

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(); } } 

6. 性能优化与注意事项

6.1 锁粒度控制

  • 分段锁:将账户按ID哈希分组
  • 读写锁:ReentrantReadWriteLock适用于读多写少场景

6.2 死锁预防

// 尝试获取锁(带超时) if(lock.tryLock(1, TimeUnit.SECONDS)) { try { // ... } finally { lock.unlock(); } } else { // 处理获取锁失败 } 

7. 与synchronized的对比分析

7.1 性能测试数据

并发线程数 ReentrantLock(ms) synchronized(ms)
10 152 210
100 1304 1852
1000 12458 15327

7.2 选择建议

  • 简单场景:synchronized
  • 需要高级功能时:ReentrantLock

8. 实际应用场景扩展

8.1 转账业务实现

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; } 

8.2 分布式系统适配

可通过Redisson等框架实现分布式锁:

RLock lock = redisson.getLock("account:"+accountId); lock.lock(); try { // 操作共享资源 } finally { lock.unlock(); } 

最佳实践总结: 1. 始终在finally块中释放锁 2. 使用while循环检查条件变量 3. 考虑使用tryLock避免死锁 4. 合理设置锁的超时时间 5. 避免在持有锁时调用外部方法 “`

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI