zoukankan      html  css  js  c++  java
  • 事务(八)

    面对高并发是锁的实现要使用aop 实现,锁不能加在方法中,应为事务一般是方法结束后提交,而锁在finally 方法中提交,从而会出现锁已经解锁而事务还没来得及提交,下个锁获得到的数据就不对。

    转载:https://www.cnblogs.com/xiohao/p/13996619.html

    自己的结论:java代码中通过加锁控制并发,一定要在事务提交后释放锁,如果先释放并发代码锁,而事务还没有提交,那么下一个并发线程获取释放的锁,进入代码,查询数据就不对,因为上一个事务还没有提交。

    所以并发锁与事务的配合有如下方案:

    1.先对方法进行AOP加锁,在方法其中调用service的事务方法。即AOP并发锁控制的方法要包含事务方法。

    2.对同一个方法加AOP并发锁以及事务@transactional注解(也是aop),这时两个aop控制同一个方法,就要注意事务的顺序问题,加锁的aop一定要在事务的aop之前,后面会讲解配置事务的前后顺序。

    3.不通过aop进行加锁,直接通过代码手动加锁,手动释放锁,一定要保证先加锁、开启事务、提交/回滚事务、释放锁这样的顺序编写代码。

    案例一

    java事务锁_java中锁与@Transactional同时使用导致锁失效的问题

    转载:https://blog.csdn.net/weixin_34614674/article/details/114053973

    示例代码

    @Transactional

    public void update(int id) {
    boolean lock = redisLock.lock(id);

    if (!lock) {
    throw new RuntimeException("当前人数过多,请稍后再试");

    }

    /*

    业务代码在该区域

    */

    redisLock.unlock(id);

    }

    问题分析

    上面这个例子是无法保证数据的一致性.由于spring的aop,会在update方法之前开启事务,之后再加锁,当锁住的代码执行完成后,再提交事务,因此锁住的代码块执行是在事务之内执行的,可以推断在代码块执行完时,事务还未提交,锁已经被释放,此时其他线程拿到锁之后进行锁住的代码块,读取的库存数据不是最新的。

    解决方法

    我们可以在update方法之前就加上锁,在还没有开事务之前就加锁,那么就可以保证线程的安全性,从而不会出现脏读和数据不一致性等情况.

    @RequestMapping("/execute")

    public void execute(int id) {
    boolean lock = redisLock.lock(id);

    if (!lock) {
    throw new RuntimeException("当前人数过多,请稍后再试");

    }

    service.update(id);

    redisLock.unlock(id);

    }

    @Transactional

    public void update(int id) {

    /*

    业务代码在该区域

    */

    }

    案例二

    java业务相关的分布式锁在service锁住,如何在提交事务的时候同时解开锁

    转载:https://ask.csdn.net/questions/993371

    因为在controller进行锁,没有所需要的业务参数,从而在service加锁,然后service执行完成解锁。
    就会存在没有提交事务而锁释放了,造成第二个请求进来数据脏读。有什么好的解决办法吗?

    可以通过拆分一个Service的事务、锁的两部分工作,拆成2个Service,

    Controller调用第一个Service(加锁、释放锁),第一个Service再调用第二个Service(事务控制部分)

    示例,修改前

     1 HelloController
     4    --HelloService
     7               事务开始
    10                  加锁
    13                      // 业务代码
    16                  解锁
    19               事务结束

    示例,修改后

    1 HelloController
    2    --LockService
    3             加锁
    4               --HelloService
    5                     事务开始
    6                          // 业务代码
    7                     事务结束
    8             解锁
    带着疑问去思考,然后串联,进而归纳总结,不断追问自己,进行自我辩证,像侦查嫌疑案件一样看待技术问题,漆黑的街道,你我一起寻找线索,你就是技术界大侦探福尔摩斯
  • 相关阅读:
    六.php小项目(2)过桥问题
    六.php小项目(1)九九乘法表
    五.php语言结构(3)break continue
    五.php语言结构(2)循环结构
    五.php语言结构(1)顺序和控制结构
    四.php运算符(6)字符串运算符和赋值运算符
    四.php运算符(5)递增递减运算符
    Day13 Java基础学习笔记
    Day12Java基础学习笔记
    Day 11Java基础学习笔记
  • 原文地址:https://www.cnblogs.com/cainiao-Shun666/p/14531312.html
Copyright © 2011-2022 走看看