最近有一個需求,需要在事務的基礎上增加鎖,實現同步,過程中使用到了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
這里是一個坑,由于在方法的外層加的事務,所以需要整個方法執行完才會提交,但是多線程情況下,第二次查找,很多情況下會查不到,因為第一次拿到鎖的事務還沒有提交