首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >向spring中的方法添加@ transactional注释。事务是在方法结束之后还是之前提交的?

向spring中的方法添加@ transactional注释。事务是在方法结束之后还是之前提交的?
EN

Stack Overflow用户
提问于 2021-07-17 14:17:49
回答 2查看 44关注 0票数 1

今天,当我学习使用“可重入锁”时,我遇到了一个问题。在售卖商品业务代码中添加锁。

代码语言:javascript
复制
@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对存储的操作结果,因而超卖。

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

EN

回答 2

Stack Overflow用户

发布于 2021-07-17 19:00:29

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

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

如前所述,@Transactional是使用方面around实现的,这意味着方法执行之前的一些代码和方法执行后的一些代码也会被执行。

所以如果你写了

代码语言:javascript
复制
@Transactional
public void method1 () {

    doSomething1;
    doSomething2;

}

spring的代理实际上看起来是什么样子

代码语言:javascript
复制
 public void method1 () {

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

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

简要回答:事务将在您编写的方法的所有语句执行完毕后关闭。

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

  • 如果您的方法抛出了检查过的异常或返回语句,或者

如果没有声明返回任何内容,则将调用提交。

票数 2
EN

Stack Overflow用户

发布于 2021-07-17 15:19:24

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68417931

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档