@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);
}