Spring @Transactional注解和ReentrantLock同步鎖同時使用不能同步的問題


結論:果在service層的方法上同時使用事務和同步鎖無法保證數據同步。

 1 @Service
 2 public class ServiceImpl{
 3         
 4     private static Lock lock = new ReentrantLock(false);
 5         
 6     @Transactional(rollbackFor = Exception.class)
 7     public void update() {
 8         try {
 9             lock.lock();
10             ... ...
11         } catch (Exception e) {
12             e.printStackTrace();
13         } finally {
14             lock.unlock();
15         }
16     }
17 }

上面這個例子無法保證數據的一致性,synchronized 同理。

原因:

  根據spring的AOP的特性,會在update方法之前開啟事務,之后再加鎖,當鎖住的代碼執行完成后,再提交事務。

  由於lock代碼塊執行是在事務之內執行的,在代碼塊執行完時,事務還未提交,因此其它線程進入synchronized代碼塊后,讀取的數據庫數據不是最新的(臟讀)。

解決方案:

  1.在還沒有開啟事務之前就加同步鎖,用加鎖的方法調用加事務的方法

 1 @Service
 2 public class ServiceImpl{
 3 
 4     private static Lock lock = new ReentrantLock(false);
 5 
 6     public void update1() {
 7         try {
 8             lock.lock();
 9             update2();
10         } catch (Exception e) {
11             e.printStackTrace();
12         } finally {
13             lock.unlock();
14         }
15     }
16 
17     @Transactional(rollbackFor = Exception.class)
18     public void uodate2() {
19         ... ...
20     }
21 }

  2.把鎖放到上一層

 1 @Controller
 2 public class TestController{
 3     @Autowired
 4     private IServiceImpl serviceImpl;
 5         
 6     private static Lock lock = new ReentrantLock(false);
 7         
 8     public String test() {
 9         try {
10             lock.lock();
11             serviceImpl.update();
12         } catch (Exception e) {
13             e.printStackTrace();
14         } finally {
15             lock.unlock();
16         }
17     }
18 }
19 
20 @Service
21 public class ServiceImpl{
22 
23     @Transactional(rollbackFor = Exception.class)
24     public void update() {
25         ... ...
26     }
27 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM