可重入锁与不可重入锁理解
测试可重入锁
概念
可重入锁就是在一段代码(多线程调用也包括)中能够重复获取同一把锁。例如:A和B两个方法同时需要获取同把锁,在A方法获取锁后,B方法同样可以获取该锁执行业务逻辑。代码
@Test void ReentrantLockTest() { long threadId = Thread.currentThread().getId(); RLock lock = redissonClient.getLock("lock" + threadId); try { boolean isLockFirst = lock.tryLock(10000L, TimeUnit.SECONDS); System.out.println(isLockFirst ? "初次获取锁成功": "初次获取锁锁失败"); boolean isLockSecond = lock.tryLock(10000L, TimeUnit.SECONDS); System.out.println(isLockSecond ? "再次获取锁成功": "再次获取锁锁失败"); } catch (InterruptedException e) { log.error(String.valueOf(e)); } finally { System.out.println("释放锁"); lock.unlock(); } }
执行结果
分析
可以看出初次获取锁成功后,没有等待锁释放,又一次成功获取了锁。这是因为Redisson利用hash结构记录线程id和重入次数。
思考
但是如果A、B两个方法同时对数据表中的同一个数据进行修改时,会不会破坏数据一致性呢?
测试不可重入锁
概念
不可重入锁就是在一段代码(多线程调用也包括)中不能够重复获取同一把锁。例如:A和B两个方法同时需要获取同把锁,在A方法获取锁后,B方法便不能获取该锁,只能被阻塞或执行失败。
代码
@Test void notReentrantLockTest() { long threadId = Thread.currentThread().getId(); try { Boolean isLockFirst = stringRedisTemplate.opsForValue().setIfAbsent("lock" + threadId, "1", 1000, TimeUnit.SECONDS); System.out.println(Boolean.TRUE.equals(isLockFirst) ? "初次获取锁成功": "初次获取锁锁失败"); Boolean isLockSecond = stringRedisTemplate.opsForValue().setIfAbsent("lock" + threadId, "1", 1000, TimeUnit.SECONDS); System.out.println(Boolean.TRUE.equals(isLockSecond) ? "再次获取锁成功": "再次获取锁锁失败"); } catch (Exception e) { log.error(String.valueOf(e)); } finally { System.out.println("释放锁"); stringRedisTemplate.delete("lock" + threadId); } }
执行结果
分析
可以看出初次获取锁成功后,再次获取锁失败了,只能等待锁被释放后才能再次加锁。