最近有一个需求,需要在事务的基础上增加锁,实现同步,过程中使用到了springboot的注解和synchronized,但是结果是同步成功,事务失败了
@Transactional
public void addUser(){
UserDO user = userDao.selectUser("eric");
if(user == null){
System.out.println("未找到用户,重新创建");
synchronized (this.getClass()) {
System.out.println("进入同步逻辑");
System.out.println("重新检查user是否存在");
UserDO user2 = userDao.selectUser("eric");
if(user2 != null){
System.out.println("user已经存在,返回");
return;
}else {
System.out.println("第二次,未找到user");
}
UserDO userDO = new UserDO();
userDO.setName("eric");
System.out.println("add user");
userDao.insertUser(userDO.getName());
System.out.println("创建成功");
}
}else{
System.out.println("第一步找到用户,返回");
}
}
执行结果如下:
未找到用户,重新创建
进入同步逻辑
重新检查user是否存在
未找到用户,重新创建
未找到用户,重新创建
未找到用户,重新创建
未找到用户,重新创建
第二次,未找到user
add user
未找到用户,重新创建
未找到用户,重新创建
未找到用户,重新创建
未找到用户,重新创建
未找到用户,重新创建
创建成功
进入同步逻辑
重新检查user是否存在
第二次,未找到user
add user
这里是一个坑,由于在方法的外层加的事务,所以需要整个方法执行完才会提交,但是多线程情况下,第二次查找,很多情况下会查不到,因为第一次拿到锁的事务还没有提交