我在Spring中使用@Transactional注释在服务方法或服务类中读取事务管理,并使用其传播,隔离,超时,readOnly属性配置事务。现在我的问题是:
1)如果我们正确使用@Transactional来实现ACID属性,我们是否还需要使用同步(使用synchronized关键字)或多线程?
2)在我们的Java EE Web应用程序中仍然使用Java多线程的不同场景是什么?
3)如果需要多线程,我们的应用程序的哪一层应该使用同步方法或块,这可能是什么原因?
我是在github上找到的虚拟网上银行项目的帮助下学习的。如果答案与这种情况相关联,那就太好了。所以这是我的课程(只是为了给你一个想法):
//Here are some entity classes
@Entity 公共类用户{...}
@Entity pulic class Account {...}
@Entity 公共类卡{...}
@Entity 公共类操作{...}
// now some DAO examples
公共类OperationDaoImpl实现OperationDao {
Page findNonCardByAccountIdAndYearMonth(Integer accountId,YearMonth yearMonth,Pageable pageable){...}
Page findTransferByAccountId(Integer accountId,Pageable pageable){...} DateTime getLastOperationDate(){...}
}
// now some service examples
@服务
@Transactional(readOnly = true)
@Validated
公共类BankServiceImpl实现BankService {
public map sumResolvedCardOperationsByAccountIdAndYearMonth(Integer accountId,YearMonth yearMonth){...}
@Transactional(readOnly = false)
public void performTransfer(Integer debitedAccountId,Integer creditedAccountId,@ Min(10)BigDecimal amount)抛出UnsufficientBalanceException {...}
}
//并且有spring-mvc控制器。
专家!很抱歉这个问题很久了。欢迎任何形式的建议。感谢。
答案 0 :(得分:4)
Web应用程序本质上是多线程的,您无需启动线程:每次请求到达Web服务器时,Web服务器都使用一个线程来处理此请求。如果在第一个请求仍在处理时进入第二个请求,则使用另一个线程来处理第二个请求,同时处理第一个请求。所以容器为你处理多线程。
所以是的,您的BankService将被多个线程同时使用。这是否意味着您需要使用同步?一点都不。 Spring服务通常是无状态的,因此线程之间不共享任何状态,这意味着不需要同步。多个线程共享的唯一状态是数据库本身。那些交易是必要的:它们确保尽管数据库将同时处理多个查询和更新,但每个事务将与其他事务隔离运行,并且提交后数据库的状态将保持一致。
请注意,每个事务都有自己的JPA持久化上下文,包含自己的JPA实体实例。因此,即使JPA实体确实具有内存状态,它们也不会在线程之间共享,因此也不需要同步。
另请注意,正如您所说,不使用同步以获得更好的性能。同步用于确保正确性。