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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端