我有这样的代码:
@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());
}
简单的方法,从所有者采取moeny并传递给接收者。这种解决方案很幼稚,因为它不能同时处理多个转移。如何确保此方法可以处理多个请求并在并发环境中安全?
答案 0 :(得分:2)
正如ghostCat所说,我们对你的环境并不熟悉,所以如果任何“看起来天真”的方法都有副作用,我们就不会知道了。
那就是说,假设这是一个非常简单直接的代码,方法名称反映了他们正在做的事情,我认为我们不必同步所有方法,而只是关键部分:
withdrawFromOwnerAccount(ownerAccount, transferModel.getAmount());
depositToReceiverAccount(receiverAccount, transferModel.getAmount());
我们可以使用帐户同步此部分:
synchronized (ownerAccount) {
withdrawFromOwnerAccount(ownerAccount, transferModel.getAmount());
}
synchronized (receiverAccount) {
depositToReceiverAccount(receiverAccount, transferModel.getAmount());
}
通过这样做,我们可以并行执行此方法,并仅在给予者/接收者已经处于执行另一个事务的过程中时锁定线程。
注意:为了应用这种方法,您必须确保同一帐户没有两个对象!