Java、转账服务和并发问题

标签 java concurrency transactions synchronized

我有这样的代码:

@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/

相关文章:

java - 创建一个 "Lock"类(它扩展了 Object 并且什么都不做)有什么好处?

mysql - mysql触发器是原子的吗?这个mysql触发器有并发问题吗?

Java EntityManager事务被破坏,如何定位导致它的SQL?

java - 当 JMS Prod 位于辅助 POJO 类中时,如何在事务中包含 JMS Producer

java - 有关 @Value 错误行为的文档

java - NamedParameterJdbcTemplate 的 update() 和 batchUpdate() 方法之间的性能和限制问题

java - IntelliJ IDEA + Maven 在 iml 文件中需要什么依赖项?

java - Play 2.2.1 Java : Whats the equivalent of @before filters from play 1. X?

Python 并发.futures : ProcessPoolExecutor fail to work

javascript - 将 webSQL 结果存储到 var 以供其他函数使用?