• 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 }
  • 相关阅读:
    jquery validate --转载
    领域驱动设计之领域模型--转载
    为system对象添加扩展方法
    DDD开源框架
    浅谈命令查询职责分离(CQRS)模式---转载
    AutoMapper小结
    执行后台任务的利器——Hangfire
    单元测试框架
    内存中的堆和栈
    ++*p,(*p)++,*p++与*++p四者的区别
  • 原文地址:https://www.cnblogs.com/xhq1024/p/11765939.html
Copyright © 2020-2023  润新知