前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >阿里Java 面试:@Transactional 和 @Async是否可以一起使用?

阿里Java 面试:@Transactional 和 @Async是否可以一起使用?

作者头像
崔认知
发布2024-04-28 12:37:18
1920
发布2024-04-28 12:37:18
举报
文章被收录于专栏:nobodynobody
上一篇博文介绍了@Transactional 和 @Async共同标注同一个方法与事务的关系:

@Transactional 和 @Async 标注同一个 service 方法会导致事务失效吗

公众号:认知科技技术团队阿里Java 面试:@Transactional 和 @Async 标注同一个 service 方法会导致事务失效吗

现介绍下@Transactional 和 @Async 标注的不同方法是否可以一起使用(相互调用)?

@Transactional 和 @Async 标注的方法可以相互被调用,但需要注意一些关键事项以确保它们按预期工作。

@Transactional 是 Spring 框架中的一个注解,用于声明一个方法或类需要事务支持。当这个方法被调用时,Spring 会为这个方法的执行创建一个新的事务或者加入一个现有的事务,如果它正在一个事务上下文中运行,但主要行为是由事务的传播行为决定。

@Async 是 Spring 中用于异步执行的注解。当你标记一个方法为 @Async,Spring 会在一个单独的线程中异步地执行这个方法。

当你结合使用 @Transactional 和 @Async 时,你需要确保事务边界正确地管理。由于 @Async 方法会在一个单独的线程中执行,如果你没有正确地配置事务传播行为,可能会出现问题。

在 @Async 方法中调用 @Transactional 方法


如果我们在 @Async 方法中调用 @Transactional 方法,Spring 会正确地管理事务并传播其上下文,从而确保数据一致性

代码语言:javascript
复制
@Async
public void transferAsync(Long depositorId, Long favoredId, BigDecimal amount) {
    transfer(depositorId, favoredId, amount);

    // other async operations, isolated from transfer
}
代码语言:javascript
复制
@Transactional
public void transfer(Long depositorId, Long favoredId, BigDecimal amount) {
    Account depositorAccount = accountRepository.findById(depositorId)
      .orElseThrow(IllegalArgumentException::new);
    Account favoredAccount = accountRepository.findById(favoredId)
      .orElseThrow(IllegalArgumentException::new);

    depositorAccount.setBalance(depositorAccount.getBalance().subtract(amount));
    favoredAccount.setBalance(favoredAccount.getBalance().add(amount));

    accountRepository.save(depositorAccount);
    accountRepository.save(favoredAccount);
}

@Async 方法中调用 @Transactional 方法可以提高性能,因为它允许与调用线程并行执行特定内部操作,而不会造成数据不一致。

在@Transactional 方法中调用 @Async 方法

Spring 目前使用 ThreadLocal 来管理当前线程的事务。因此,它不会在不同线程之间共享线程上下文。

因此,如果一个使用 @Transactional 注解的方法调用了一个使用 @Async 注解的方法,Spring 不会传播相同的事务线程上下文。

这意味着,在异步方法中执行的事务不会与调用线程的事务共享相同的上下文。每个线程都有其自己的 ThreadLocal 变量副本,这意味着每个线程都有其自己的事务上下文。当从事务方法调用异步方法时,需要特别注意这一点,以确保数据的一致性和完整性。如果需要保持事务的上下文,可能需要采取额外的措施,如使用特定的传播行为或捕获并处理异步方法中可能发生的异常。

因此,为了避免这种数据一致性问题,我们必须避免从 @Transactional 方法中调用 @Async 方法,因为不会发生线程上下文传播

总之,@Transactional 和 @Async 标注的方法可以被相互调用,但需要确保你了解并正确处理了相关的复杂性和潜在问题。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-04-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 认知科技技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档