@Transactional事务中使用锁坑(@Transactional事务中使用锁失效)

@Transactional事务中使用锁失效

说明:
Spring中使用注解@Transactional作事务管理,@Transactional注解在方法上时,是方法完成之后才进行提交事务的

测试代码(伪代码):

@RequestMapping("/add")
    public void addEmploye(){
        for (int i=0;i<1000;i++){
            new Thread(() -> 	detailService.addEmployee()).start();
        }
    }
     @Transactional
    public synchronized void addEmployee() {
        Employee employee = employeeRepository.getOne(8);
        System.out.println(employee);
        Integer age = employee.getAge();
        employee.setAge(age + 1);
		//修改id =8 的employee的年龄+1
        employeeRepository.update(employee);
    }

坑:使用@Transactional注解开启事务管理,假如线程一调用addEmployee获取锁调用addEmployee()方法之后但这时还未提交事务,数据库中id =8 该条记录还未有做更新,线程一释放锁,线程二获取到锁调用完方法之后和线程一恰好一起提交事务,此时可能会造成数据库表被锁(或死锁),出现异常之后由于使用@Transactional事务会造成线程一和线程二都没有修改到数据库记录
注意:无论是使用synchronized 作锁或是使用redis作锁都会有可能这种情况发生,在事务中使用锁无效!!!

解决:在调用事务方法之前就要加锁

@RequestMapping("/add")
    public void addEmploye(){
        for (int i=0;i<1000;i++){
            new Thread(() -> 	detailService.add()).start();
        }
    }
    public synchronized  void add(){ // 解决事务中使用锁失效
    	addEmployee()
    }
     @Transactional
    public void addEmployee() {
        Employee employee = employeeRepository.getOne(8);
        System.out.println(employee);
        Integer age = employee.getAge();
        employee.setAge(age + 1);
		//修改id =8 的employee的年龄+1
        employeeRepository.update(employee);
    }
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring框架使用@Async注解可以将一个方法标记为异步执行,该方法会在一个新的线程执行。而@Transactional注解用于开启事务,用于保证数据的一致性。 当一个被@Async注解的方法调用一个被@Transactional注解的方法时,会出现事务失效的情况。这是因为@Transactional注解只能在当前线程开启事务,而异步方法是在新的线程执行的,与当前线程不在同一个线程,因此无法获取当前线程事务上下文。 为了解决这个问题,可以使用Spring提供的异步事务处理机制。具体来说,可以在@Async注解的方法上添加@Transaction注解,并设置propagation属性为REQUIRES_NEW,表示开启一个新的事务。这样,在异步方法执行的数据库操作就可以在新的事务进行,不会影响到当前线程事务。 举个例子: ``` @Service public class UserService { @Autowired private UserRepository userRepository; @Async @Transactional(propagation = Propagation.REQUIRES_NEW) public void updateUser(User user) { userRepository.save(user); } } ``` 在上述例子,updateUser方法使用了@Async和@Transactional注解,@Async注解表示该方法是异步执行的,@Transactional注解设置propagation属性为REQUIRES_NEW,表示开启一个新的事务。 总之,为了避免@Async修饰的方法@Transactional事务失效,需要在异步方法使用@Transaction注解开启一个新的事务

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值