可重入锁与不可重入锁理解

测试可重入锁

概念

  可重入锁就是在一段代码(多线程调用也包括)中能够重复获取同一把锁。例如: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);
        }
    }

执行结果

 分析

  可以看出初次获取锁成功后,再次获取锁失败了,只能等待锁被释放后才能再次加锁。

 

posted @ 2024-06-26 10:50  梁哲  阅读(111)  评论(0)    收藏  举报