同步和@Transactional让我感到困惑

时间:2015-05-16 19:36:17

标签: java multithreading spring java-ee spring-transactions

我在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控制器。

专家!很抱歉这个问题很久了。欢迎任何形式的建议。感谢。

1 个答案:

答案 0 :(得分:4)

Web应用程序本质上是多线程的,您无需启动线程:每次请求到达Web服务器时,Web服务器都使用一个线程来处理此请求。如果在第一个请求仍在处理时进入第二个请求,则使用另一个线程来处理第二个请求,同时处理第一个请求。所以容器为你处理多线程。

所以是的,您的BankService将被多个线程同时使用。这是否意味着您需要使用同步?一点都不。 Spring服务通常是无状态的,因此线程之间不共享任何状态,这意味着不需要同步。多个线程共享的唯一状态是数据库本身。那些交易是必要的:它们确保尽管数据库将同时处理多个查询和更新,但每个事务将与其他事务隔离运行,并且提交后数据库的状态将保持一致。

请注意,每个事务都有自己的JPA持久化上下文,包含自己的JPA实体实例。因此,即使JPA实体确实具有内存状态,它们也不会在线程之间共享,因此也不需要同步。

另请注意,正如您所说,不使用同步以获得更好的性能。同步用于确保正确性。