简体   繁体   English

同步和@Transactional使我感到困惑

[英]Synchronization and @Transactional confuses me

I read about transaction management in spring using @Transactional annotation in our service methods or on service class and configuring our transaction with its propagation, isolation, timeout, readOnly attributes. 我在春季在服务方法中或在服务类上使用@Transactional注释并使用其传播,隔离,超时,readOnly属性配置事务来了解有关事务管理的信息。 Now my question is: 现在我的问题是:

1) Do we still need to use synchronization (using synchronized keyword) or multi-threading if we are using @Transactional appropriately to achieve ACID properties? 1)如果我们适当地使用@Transactional来实现ACID属性,是否还需要使用同步(使用synced关键字)或多线程?

2) What could be the different scenarios to still use java multi-threading in our Java EE web-application? 2)在我们的Java EE Web应用程序中仍然使用Java多线程的情况可能是什么?

3) If multi-threading is required, what layer of our application should be using synchronized methods or blocks and what could be the reasons for that ? 3)如果需要多线程,那么应用程序的哪一层应使用同步方法或块,这可能是什么原因?

I'm learning with the help of a dummy Online Banking project which I found in github. 我正在github中找到的虚拟网上银行项目的帮助下学习。 So it would be nice if the answers are connected to this scenario. 因此,如果答案与这种情况相关,那将是很好的。 So here are my classes (just to give you a idea): 这是我的课程(仅供参考):

//Here are some entity classes

@Entity public class User{...} @Entity公共类用户{...}

@Entity pulic class Account{...} @Entity公共类帐户{...}

@Entity public class Card{...} @Entity公共类卡{...}

@Entity public class Operation{...} @Entity公共类操作{...}

// now some DAO examples

public class OperationDaoImpl implements OperationDao { 公共类OperationDaoImpl实现OperationDao {

Page findNonCardByAccountIdAndYearMonth(Integer accountId, YearMonth yearMonth, Pageable pageable){...} 页面findNonCardByAccountIdAndYearMonth(整数accountId,YearMonth yearMonth,可分页的可分页){...}

Page findTransferByAccountId(Integer accountId, Pageable pageable){...} DateTime getLastOperationDate(){...} 页面findTransferByAccountId(整数accountId,可分页的可分页){...} DateTime getLastOperationDate(){...}

} }

// now some service examples

@Service @服务

@Transactional(readOnly = true) @Transactional(readOnly = true)

@Validated @Validated

public class BankServiceImpl implements BankService { 公共类BankServiceImpl实现BankService {

public Map sumResolvedCardOperationsByAccountIdAndYearMonth(Integer accountId, YearMonth yearMonth) {...} 公共地图sumResolvedCardOperationsByAccountIdAndYearMonth(Integer accountId,YearMonth yearMonth){...}

@Transactional(readOnly = false) @Transactional(readOnly = false)

public void performTransfer(Integer debitedAccountId, Integer creditedAccountId, @Min(10) BigDecimal amount) throws UnsufficientBalanceException {...} 公共无效的performTransfer(Integer debitedAccountId,Integer creditedAccountId,@Min(10)BigDecimal量)引发UnsufficientBalanceException {...}

} }

// and there are spring-mvc controllers. //还有spring-mvc控制器。

Guys! 伙计们! sorry for making this question this long. 很抱歉提出这个问题这么长时间。 Any kind of suggestion is welcome. 任何建议都是值得欢迎的。 Thanks. 谢谢。

A web application is multi-threaded by nature, without you ever having to start threads: each time a request comes to the web server, the web server uses a thread to handle this request. Web应用程序本质上是多线程的,而您不必启动线程:每次请求到达Web服务器时,Web服务器都会使用线程来处理此请求。 If a second request comes in while the first one is still handled, another thread is used to handle the second request, concurrently with the first one. 如果在仍处理第一个请求的同时出现第二个请求,则使用另一个线程与第一个请求同时处理第二个请求。 So the container handles the multi-threading for you. 因此,容器可以为您处理多线程。

So yes, your BankService will be used by multiple threads concurrently. 所以是的,您的BankService将同时被多个线程使用。 Does that mean you need to use synchronization? 这是否意味着您需要使用同步? No, not at all. 一点都不。 A Spring service is typically stateless, and no state is thus shared between threads, meaning that no synchronization is necessary. Spring服务通常是无状态的,因此线程之间不会共享任何状态,这意味着不需要同步。 The only state that is shared by multiple threads is the database itself. 由多个线程共享的唯一状态是数据库本身。 And that's where transactions are necessary: they ensure that although the database will handle multiple queries and updates concurrently, each transaction will run in isolation from the others, and that the state of the database after a commit will consistent. 这就是必须进行事务处理的地方:它们确保尽管数据库将同时处理多个查询和更新,但是每个事务将独立于其他事务运行,并且确保提交后数据库的状态保持一致。

Note that each transaction will have its own JPA persistence context, containing its own instances of the JPA entities. 请注意,每个事务将具有自己的JPA持久性上下文,其中包含其自己的JPA实体实例。 So, even if JPA entities do have in-memory state, they are not shared between threads and thus don't require synchronization either. 因此,即使JPA实体确实具有内存中状态,也不会在线程之间共享它们,因此也不需要同步。

Also note that synchronization is not used, as you're saying, to have better performance. 还要注意,正如您所说的那样,不使用同步来获得更好的性能。 Synchronization is used to ensure correctness. 同步用于确保正确性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM