Synchronization and @Transactional confuses me

0 votes
asked May 16, 2015 by prabhat-kumar

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. 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?

2) What could be the different scenarios to still use java multi-threading in our Java EE web-application?

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 ?

I'm learning with the help of a dummy Online Banking project which I found in 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 pulic class Account{...}

@Entity public class Card{...}

@Entity public class Operation{...}

// now some DAO examples

public class OperationDaoImpl implements OperationDao {

Page findNonCardByAccountIdAndYearMonth(Integer accountId, YearMonth yearMonth, Pageable pageable){...}

Page findTransferByAccountId(Integer accountId, Pageable pageable){...} DateTime getLastOperationDate(){...}

}

// now some service examples

@Service

@Transactional(readOnly = true)

@Validated

public class BankServiceImpl implements BankService {

public Map sumResolvedCardOperationsByAccountIdAndYearMonth(Integer accountId, YearMonth yearMonth) {...}

@Transactional(readOnly = false)

public void performTransfer(Integer debitedAccountId, Integer creditedAccountId, @Min(10) BigDecimal amount) throws UnsufficientBalanceException {...}

}

// and there are spring-mvc controllers.

Guys! sorry for making this question this long. Any kind of suggestion is welcome. Thanks.

1 Answer

+4 votes
answered May 16, 2015 by jb-nizet

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. 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. 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. 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. So, even if JPA entities do have in-memory state, they are not shared between threads and thus don't require synchronization either.

Also note that synchronization is not used, as you're saying, to have better performance. Synchronization is used to ensure correctness.

Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...