我有这样的代码:
@Transactional(rollbackOn = RuntimeException.class)
synchronized public void transfer(@NonNull final TransferModel transferModel) {
log.info("Start processing money transfer from user: {} to receiver: {}. Transfer amount: {}", transferModel.getOwnerId(), transferModel
.getReceiverId(), transferModel.getAmount());
final AccountEntity ownerAccount = findByOwner(transferModel.getOwnerId());
final AccountEntity receiverAccount = findByOwner(transferModel.getReceiverId());
log.info("Owner balancer before transfer: {}. Receiver balance before transfer {}", ownerAccount.getBalance(), receiverAccount.getBalance());
if (ownerAccount.getBalance().compareTo(transferModel.getAmount()) < 0) {
throw new IllegalArgumentException("Owner has insufficient amount of money");
}
withdrawFromOwnerAccount(ownerAccount, transferModel.getAmount());
depositToReceiverAccount(receiverAccount, transferModel.getAmount());
log.info("Transfer money finished successful");
log.info("Owner balancer after transfer: {}. Receiver balance after transfer {}", ownerAccount.getBalance(), receiverAccount.getBalance());
}
简单的方法,从所有者那里收取金钱并传递给接收者。这个解决方案很幼稚,因为它一次不能处理多个传输。如何确保此方法能够处理多个请求并在并发环境中安全?
最佳答案
正如 GhostCat 提到的,我们不熟悉您的环境,因此如果任何“看起来天真”的方法有副作用,我们不会知道。
也就是说,假设这是一个非常简单明了的代码,并且方法名称反射(reflect)了它们正在做什么,我认为我们不必同步所有该方法,但只是关键部分:
withdrawFromOwnerAccount(ownerAccount, transferModel.getAmount());
depositToReceiverAccount(receiverAccount, transferModel.getAmount());
我们可以使用帐户同步这部分:
synchronized (ownerAccount) {
withdrawFromOwnerAccount(ownerAccount, transferModel.getAmount());
}
synchronized (receiverAccount) {
depositToReceiverAccount(receiverAccount, transferModel.getAmount());
}
通过这样做,我们能够并行执行此方法,并且仅当给予者/接收者已经在执行另一个事务时才锁定线程。
注意:为了应用此方法,您必须确保同一帐户没有两个对象!
关于Java、转账服务和并发问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45207492/