我在确保转账方法是线程安全的方面遇到了问题。在账户类中,我有一组传入和传出转账。当从 A 到 B 的多个转账同时发生时,raceCondition 就会出现问题。
我尝试在帐户存储库上实现悲观锁,特别是在 findById 方法上,但竞争条件仍然可能发生。怎么解决这个问题呢?我应该直接在方法中而不是在存储库上加锁吗?或者也许采用乐观锁定?我浏览了过去的主题,发现悲观锁定比乐观锁定更适合此类用途。还是我错了?
public interface AccountRepository extends JpaRepository<Account, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
Optional<Account> findById(Long accountId);
}
public interface TransferRepository extends JpaRepository<Transfer, Long>, JpaSpecificationExecutor<Transfer> {
}
@Transactional
public Transfer makeTransfer(CreateTransferCommand command) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentUsername = authentication.getName();
Account sourceAccount = accountRepository.findById(command.getSourceAccountId())
.orElseThrow(() -> new EntityNotFoundException("Source account not found"));
if (!sourceAccount.getUsername().equals(currentUsername)) {
throw new WrongOwnerException("User does not own the source account");
}
Account destinationAccount = accountRepository.findById(command.getDestinationAccountId())
.orElseThrow(() -> new EntityNotFoundException("Destination account not found"));
if (sourceAccount.getBalance().compareTo(command.getAmount()) < 0) {
throw new NotEnoughMoneyException("Source account does not have enough balance");
}
sourceAccount.setBalance(sourceAccount.getBalance().subtract(command.getAmount()));
destinationAccount.setBalance(destinationAccount.getBalance().add(command.getAmount()));
Transfer transfer = new Transfer();
transfer.setSourceAccount(sourceAccount);
transfer.setDestinationAccount(destinationAccount);
transfer.setAmount(command.getAmount());
transfer.setTitle(command.getTitle());
transfer.setTransferDate(LocalDateTime.now());
return transferRepository.save(transfer);
}
告诉我你是如何解决这个问题的,因为我也有同样的问题! :D