【问题标题】:Add @ transactional annotation to the method in spring. Is the transaction submitted after or before the end of the method?在spring的方法中添加@transactional注解。交易是在方法结束之后还是之前提交?
【发布时间】:2021-07-17 06:17:49
【问题描述】:

今天在学习使用'reentrant lock'锁的时候,遇到了一个问题。将锁添加到已售商品业务的代码中。

@Service
public class ServiceOne{
    private Lock lock = new ReentrantLock(true);
    public Result  func(long seckillId, long userId) {
        lock.lock();
        // Check stock
        // sale
        // Reduce stock
        lock.unlock();
    }
}

前提是使用MySQL数据库的重读隔离机制。在高并发的情况下,假设有多个线程同时调用该方法。当交易在'lock'和'unlock'之间可以完全打开和提交时,就不存在超卖问题了。

显然,事务必须在'lock'之后才开始,所以关键是事务是否必须在'unlock'之前提交。 如果是在'unlock'之后,那么就真的有可能超卖了:比如线程1执行完方法,但是事务还没有提交,线程2拿到锁,开始执行方法。在“可重复读”隔离机制下,线程2无法读取线程1对store的操作结果,因此超卖。

希望你能来回答你的问题!感激不尽!

【问题讨论】:

  • @Transactional 被实现为“环绕”建议。

标签: java mysql spring


【解决方案1】:

事务是在方法结束之后还是之前提交?

您的方法不仅仅是 Spring 实际执行的方法。 Spring 使用代理,因此您可以为您的类和您的方法创建一个代理。

正如已经评论过的,@Transactional 是使用切面 around 实现的,这意味着在您的方法执行之前的一些代码以及在您的方法执行之后的一些代码。

如果你写过

@Transactional
public void method1 () {

    doSomething1;
    doSomething2;

}

spring 的代理实际上可能是什么样子

 public void method1 () {

        /*
          Extra code from spring to open a transaction.
        /*
    
        doSomething1;
        doSomething2;

        /*
          Extra code from spring to close a transaction.
        /*
    }

简答:在您编写的方法的所有语句都执行后,事务将被关闭。

  • 如果您的方法以抛出未经检查的异常结束,则将调用回滚。

  • 如果您的方法完成抛出检查异常或返回语句或 void 如果没有声明要返回,则将调用提交。

【讨论】:

    【解决方案2】:

    @Transactional 用于使该操作成为原子操作。表示在方法结束时执行解锁。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-22
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多