Spring annotations and synchronization locks cannot solve the synchronization problem
This article mainly introduces how to solve the problem that spring annotations and synchronization locks cannot be synchronized. It is introduced in great detail through the example code, which has a certain reference value for everyone's study or work. Friends in need can refer to it
Conclusion: if transaction and synchronization lock are used simultaneously in the method of service layer, data synchronization cannot be guaranteed.
@Service public class ServiceImpl{ private static Lock lock = new reentrantlock(false); @Transactional(rollbackFor = Exception.class) public void update() { try { lock.lock(); ... ... } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }
The above example cannot guarantee the consistency of data. The same is true for synchronized.
reason:
According to the AOP characteristics of spring, the transaction will be opened before the update method, and then locked. When the locked code is executed, the transaction will be committed.
Because the lock code block is executed within the transaction, the transaction has not been committed when the code block is executed. Therefore, after other threads enter the synchronized code block, the database data read is not the latest (dirty read).
Solution:
1. Add a synchronization lock before the transaction is opened, and call the transaction adding method with the locking method
@Service public class ServiceImpl{ private static Lock lock = new reentrantlock(false); public void update1() { try { lock.lock(); update2(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } @Transactional(rollbackFor = Exception.class) public void uodate2() { ... ... } }
2. Put the lock on the upper floor
@Controller public class TestController{ @Autowired private IServiceImpl serviceImpl; private static Lock lock = new reentrantlock(false); public String test() { try { lock.lock(); serviceImpl.update(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } } @Service public class ServiceImpl{ @Transactional(rollbackFor = Exception.class) public void update() { ... ... } }
The above is the whole content of this article. I hope it will help you in your study, and I hope you will support us a lot.