Synchronized, as we all know, is an atomic built-in lock provided by Java. Its implementation principle is to achieve synchronization through the acquisition of the object monitor. Only when the thread obtains the object monitor can it continue to execute, otherwise the thread blocks (wait). Example:

public class DemoServiceImpl { @Autowired private DemoDao demoDao; + 1 @Transactional public synchronized String getSn(Long ID) {DemoSn sn = demodao.getSnById (id); sn.setSn(sn.getSn() + 1); demoDao.update(sn);returnsn.getSn().toString(); }}Copy the code

To describe a code example: This method involves ++ 1, and there are data security issues when multiple threads call the method, so I added Synchronized to ensure that only one thread is allowed in at a time.

It was thought that Synchronized was added here, which means thread-safe. However, after testing, it was found that Synchronized lock did not work, and multiple threads still returned the same value when calling the method.

A brief introduction to the Spring @Transactional execution principle: The @Transactional annotation is an annotation that Spring provides to control a transaction. When the annotation is marked ona method, AOP enhancements (dynamic proxies) are made to that method, then the transaction is opened before the method executes and committed after execution.

If the above example method only adds Synchronized and does not specify @transactional, getSn() allows only one thread to enter at a time because of a synchronization lock:

A(thread): DemoServiceImpl#getSn() > B(thread): DemoServiceImpl#getSn() If the sample method above adds Synchronized and marks the @Transactional thread for execution:

A(thread): Spring commits transactional > DemoServiceImpl#getSn() > Spring commits transactional

B(thread): Spring commits transactional > DemoServiceImpl#getSn() > Spring commits transactional

Here there seems to be no problem, open transaction -> execute method body -> commit transaction, but here is exactly the key to Synchronized failure.

Key causes of Synchronized failure: Because Synchronized locks the currently invoked method object, while Spring AOP processes transactions to generate a proxy object, start the transaction before the proxy object executes the method, and commit the transaction after the method executes, so to speak, Transactions are opened and committed outside the scope of Synchronized locking. Synchronization locks are failure reason is: when A (thread) performed getSn () method, which will be released synchronization lock, and to commit the transaction, but has not yet submitted after the transaction in A (thread), B (threads) to perform getSn () method, after the execution with A (threads) to commit the transaction, will appear at this time of thread safety.

BLOG address: www.liangsonghua.com

Pay attention to wechat public number: songhua preserved egg bulletin board, get more exciting!

Introduction to our official account: We share our technical insights from working in JD, as well as JAVA technology and best practices in the industry, most of which are pragmatic, understandable and reproducible