spring synchronized锁和事务
最近发现有同事写了一段事务控制的方法中子方法加了锁的代码,而且在事务上用了propagation = Propagation.REQUIRES_NEW,然后稍微研究了下,得出以下结论:
- propagation = Propagation.REQUIRES_NEW在执行方法时,不管之前有没有事务,都会创建新的事务,而且这个一般用于嵌套事务的内层事务中,像xxx那样写也有效,不过一般不那样用。
- 目前用的是事务(_NEW)在外层,锁在内层的写法,这种写法有风险。并发情况下,A在执行有锁的部分并且有自己的事务,B进来时会创建自己的事务(因为用了_NEW)并且等A执行完有锁的部分。等A执行完有锁的部分,A事务开始执行save,B开始执行有锁的部分,如果A save还没提交,B还是会拿到旧的。 间隔时间很短的情况会取到旧数据,人工很难重现。
- 如果继续用这种写法,但不用_NEW,用默认事务,会这样子:在执行有锁的部分并且有自己的事务,B进来时会用A的事务并且等A执行完有锁的部分。等A执行完有锁的部分,A事务开始执行save,B开始执行有锁的部分,如果B save还没提交,A save也不会提交,这样B拿到的肯定是旧的。而且这样很乱,肯定是错的。
建议写法是锁在外层,事务在内层,这样事务就会被锁管理,事务执行完后锁才会被释放,原理是锁管理事务。
在service层如果用一个加锁的外层函数调用有事务控制的方法,sonarQube(一个代码风格检查工具)提示可能会有问题,后面在controller那边加了锁,不过之后还是要看下在service层到底有什么问题。
还没有评论,来说两句吧...