我需要从数据库中读取数据,执行一些逻辑,然后在一次原子操作中将数据写入数据库。
我需要确保此操作是完全线程安全的,因为可能有许多线程使用此代码。
我现在正在做的事情是这样的:
@Component
@Scope("prototype")
public class AccountBalanceChangeHandlerImpl implements AccountBalanceChangeHandler {
private final Object mutex = new Object();
@Inject
private UserAccountRepository userAccountRepository;
@Override
public Money handle(Long userAccountId, Money money) throws Exception {
synchronized (mutex) {
UserAccount userAccount = userAccountRepository.findOne(userAccountId);
if (userAccount.getMoney().getCurrencyUnit().equals(money.getCurrencyUnit())) {
userAccount.setMoney(userAccount.getMoney().plus(money));
} else {
BigDecimal currencyRate = getCurrencyConvertRate(money.getCurrencyUnit().getCurrencyCode(),
userAccount.getMoney().getCurrencyUnit().getCurrencyCode());
userAccount.setMoney(userAccount.getMoney().plus(money
.convertedTo(userAccount.getMoney().getCurrencyUnit(), currencyRate, RoundingMode.HALF_UP)));
}
userAccountRepository.save(userAccount);
return userAccount.getMoney();
}
}
private BigDecimal getCurrencyConvertRate(String from, String to) throws Exception {
//something here
}
}
这段代码似乎是线程安全的 - 我在10到10000个线程上测试它并且不能使它不起作用 - 在删除synchronized块后它失败了。
我只是想知道有没有办法在数据库级别处理它或者做得更好?
我已经在很多方面阅读了很多关于交易,锁定和尝试@Transactional和@Lock的内容,但我无法让它发挥作用。