72、缓存---分布式锁---Redisson的Lock锁测试


@GetMapping("/hello")
    @ResponseBody
    public String hello(){
        //1、获取一把锁,只要是锁的名字一样,就是同一把锁
        RLock lock = redissonClient.getLock("my-lock");

        //2、加锁
        lock.lock();//阻塞式等待
        try {
            System.out.println("加锁成功,执行业务。。。" + Thread.currentThread().getId());
            Thread.sleep(30000);//睡眠,模拟超长业务
        }catch (Exception e){

        }finally {
            //3、解锁
            System.out.println("释放锁。。。" + Thread.currentThread().getId());
            lock.unlock();
        }

        return "hello";
    }

假如多个线程一块执行hello请求,一个线程抢占到锁后,在释放锁之前突然宕机,释放锁失败。这样别的线程还能请求到锁吗?
答案是可以的! 因为redisson有一个看门狗机制。
redisson加的锁都是阻塞式等待,默认加锁都是30s时间
1、锁的自动续期,如果业务超长,运行期间自动给锁续上新的30s。不用担心业务时间长,锁自动过期被删除
2、加锁的业务只要运行完成,就不会给当前锁续期,即使不手动解锁,锁默认在30s以后自动删除。

也可以自己指定锁的过期时间: lock.lock(10, TimeUnit.SECONDS);//阻塞式等待
但是要注意,我们指定过期时间这个方法,不会像上面那样会自动续期,所以我们在多线程情况下必须设置的锁的过期时间要大于我们业务的执行时间才可以

原理:

1、如果我们传递了锁的超时时间,就发送给redis执行脚本,进行占锁,默认超时就是我们指定的时间

2、如果我们未传递了锁的超时时间,就使用30*1000【默认看门狗的时间】,只要占锁成功,就会启动一个定时任务,【重新给锁设置过期时间,新的过期时间就是看门狗的默认事件】,每隔10s都会自动续期。


但是我们在实战中还是使用自己指定过期时间的方法,因为这样不用自动续期,提高效率。只要我们指定过期时间大于业务时间即可。比如30s