如果你不懂锁和事务同时使用的问题,你一定不是一个合格的程序员

如果你不懂锁和事务同时使用的问题,你一定不是一个合格的程序员


这里直接写一些伪代码,插入一条测试记录(mysql隔离级别是可重复读)

@Transactional
public void insertTestData(){
  //新建锁,3000为获取锁的等待时间3秒
  Lock lock=new lock(3000);
  //尝试获取锁
  boolean flag=lock.tryLock();
  //如果获取锁成功
  if(flag){
    try{
      //通过手机号查询用户使用存在
      User user=userDao.selectOne("13216195342");
      if(user==null){
         //如果用户不存在,则插入新用户
         userDao.insert("手机号为13216195342的用户");
         }
    }finally{
    //释放锁
     lock.unlock();
    }
  }
}

上面就是锁和事务同时使用的一段最常见的伪代码,那么你能看出来有什么问题吗?考虑一下并发的情况,或者一些异常情况导致的并发,比如前端没有处理好,用户点击了一下,前端代码在极短的时间里面访问了后端接口两次,那么这段代码有问题吗?
答案是肯定的,有问题,那么问题出在哪儿呢
咱们先来看看如果没有并发的情况,在插入用户数据的时候首先判断了一下这个手机号对应的用户是否存在,如果不存在则插入新用户,这是没有问题的,但是如果在并发的情况下,在极短时间里面过来两条会出现什么问题呢?
spring会同时开启两个事务,由于事务具有隔离性,第一个线程即使提交了事务,第二个线程也无法查询到有手机号对应的记录,就导致重复插入相同手机号的记录了,如果这一块儿你不太明白的话,建议好好查询一下事务的隔离级别,所以这里是存在问题的
那么如何解决呢
解决方法就是再新建一个service,把开启事务的保存的方法放到另外一个service中,锁直接锁service中的保存方法,这样就不能同时开启多个事务了,有不明白的可以留言讨论

你可能感兴趣的:(java)