7

我有一个关于 @Transactional 注释如何单独管理代码和事务执行的问题。给定正确设置的 Spring 应用程序和以下代码:

@Transactional
public void withdraw(int amount) {
    if(isEnoughFunds(amount)) {
        decreaseFunds(amount);
    }
}

是否有可能出现以下情况:

  • 资金 == 100;金额 == 100
  • 线程 A 进入提现/事务 A 开始
  • 线程 A 执行 isEnoughFunds 评估结果为 true
  • 线程 B 进入提现/事务 B 开始
  • 线程 B 执行 isEnoughFunds 评估结果为 true
  • 线程 A 执行 reductionFunds / 线程 A 锁定 db 记录
  • 线程 B 等待线程 A 提交事务并释放写锁
  • 线程 A 退出退出 / 事务 A 提交
  • 线程 B 执行 reductionFunds / 线程 B 锁定 db 记录
  • 线程 B 退出退出 / 事务 B 提交
  • 资金 == -100

如果这是可能的,您将如何防止这种情况发生?

4

1 回答 1

3

是的,这是可能的,具体取决于隔离级别。为了防止这种情况,您可以在调用 ifEnoughFunds() 之前从数据库中显式获取读锁。锁将在事务结束时释放。在这种情况下,线程 B 将始终等待线程 A 的事务提交,然后再进行检查。

于 2012-09-26T16:58:52.127 回答