背景
假设我们正在开发一个在线银行系统,一个关键功能是用户账户的转账操作。在转账过程中,系统需要检查账户余额是否足够,余额充足,则执行转账;余额不足,则返回错误信息。下面是一个简化的Java代码片段,用于处理转账逻辑:
java
public class TransferService {
public String transferMoney(String fromAccount, String toAccount, double amount) {
double fromBalance = getBalance(fromAccount);
double toBalance = getBalance(toAccount);
if (fromBalance >= amount) {
// 执行转账操作
setBalance(fromAccount, fromBalance – amount);
setBalance(toAccount, toBalance + amount);
return "Transfer successful";
} else {
return "Insufficient funds";
}
}
private double getBalance(String account) {
// 模拟获取账户余额的方法
return 1000.0; // 假设所有账户余额都是1000.0
}
private void setBalance(String account, double newBalance) {
// 模拟设置账户余额的方法
}
}
提出
在上面的代码中,有一个业务逻辑BUG。请这个BUG,并说明如何修复它。
BUG
在上述代码中,`getBalance`方法被调用了两次,分别在获取`fromAccount`和`toAccount`的余额时。账户余额在两次查询之间发生变化(另一个线程正在执行转账操作),`fromBalance`和`toBalance`可能会出现不一致的情况,导致转账失败或者错误地执行转账。
修复方案
为了修复这个BUG,我们可以采取步骤:
1. 使用同步代码块来确保在获取账户余额和更新账户余额时,不会有其他线程操作这些数据。
2. 在同步块内,先更新`fromAccount`的余额,再更新`toAccount`的余额。
3. 在更新`fromAccount`的余额时余额不足,则不需要继续执行转账操作,直接返回错误信息。
下面是修复后的代码:
java
public class TransferService {
public String transferMoney(String fromAccount, String toAccount, double amount) {
synchronized (fromAccount) {
synchronized (toAccount) {
double fromBalance = getBalance(fromAccount);
double toBalance = getBalance(toAccount);
if (fromBalance >= amount) {
// 执行转账操作
setBalance(fromAccount, fromBalance – amount);
setBalance(toAccount, toBalance + amount);
return "Transfer successful";
} else {
return "Insufficient funds";
}
}
}
}
private double getBalance(String account) {
// 模拟获取账户余额的方法
return 1000.0; // 假设所有账户余额都是1000.0
}
private void setBalance(String account, double newBalance) {
// 模拟设置账户余额的方法
}
}
在这个修复方案中,我们使用了两层同步,确保了在执行转账操作时,账户余额的一致性。外层同步块确保了在修改任何账户余额之前,不会有其他线程正在修改账户余额。内层同步块确保了`fromAccount`和`toAccount`的余额获取和更新是原子操作,防止了并发修改的。
通过这样的修改,我们可以确保即使在多线程环境下,转账操作也是线程安全的,可以正确处理余额不足的情况。
还没有评论呢,快来抢沙发~