Redis|在Spring事务管理下,Synchronized为啥还线程不安全?( 二 )

<1){ log.info("把录播的信息插入数据库失败 参数是->{}", JSON.toJSONString(courseChapterLiveRecord)); throw new RRException("把录播的信息插入数据库失败"); }}其实也就是说把事务包裹在Synchronized 里面
先自我批评一下在技术的道路上真的不要自己觉得是什么就是什么 上面的代码是错误的 其实我并没有测试过 就贴到文章上了 这是一个大忌 为什么很多技术文章有问题 因为很多就像我上面的一样 所以敦促自己以后做事情还是要扎扎实实
感谢 紫雨飞星 读者提出我的错误 具体错误的原因是因为调用savRecord方法的时候使用的是this对象 , 其实是没有被AOP处理的 , 也就是这个Transactional不会生效~~~
修改后的代码 自己注入自己
@Override public synchronized void saveCourseChapterLiveRecord(CourseChapterLiveRecord courseChapterLiveRecord) { courseChapterLiveRecordServiceImpl.saveRecord(courseChapterLiveRecord); } @Transactional public void saveRecord(CourseChapterLiveRecord courseChapterLiveRecord) { //先查数据看是否已经存了 if (findOrder(courseChapterLiveRecord)){ return;} int row = this.insertSelective(courseChapterLiveRecord); if (row<1){ log.info("把录播的信息插入数据库失败 参数是->{}", JSON.toJSONString(courseChapterLiveRecord)); throw new RRException("把录播的信息插入数据库失败"); }}利用中午的时间测了几次 确实是不会出现线程安全问题了
方案3 用redis 分布式锁 也是可以的 就算是多个副本也是能保证线程安全 。 这个后面的文章会有写到
结论在多线程环境下 , 就可能会出现:方法执行完了(synchronized代码块执行完了) , 事务还没提交 , 别的线程可以进入被synchronized修饰的方法 , 再读取的时候 , 读到的是还没提交事务的数据 , 这个数据不是最新的 , 所以就出现了这个问题 。
【Redis|在Spring事务管理下,Synchronized为啥还线程不安全?】Synchronized 失效关键原因:是因为Synchronized锁定的是当前调用方法对象,而Spring AOP 处理事务会进行生成一个代理对象 , 并在代理对象执行方法前的事务开启 , 方法执行完的事务提交 , 所以说 , 事务的开启和提交并不是在 Synchronized 锁定的范围内 。 出现同步锁失效的原因是:当A(线程) 执行完insertSelective()方法 , 会进行释放同步锁 , 去做提交事务 , 但在A(线程)还没有提交完事务之前 , B(线程)进行执行findOrder() 方法 , 执行完毕之后和A(线程)一起提交事务, 这时候就会出现线程安全问题 。