redis分布式锁(看门枸机制)

分布式锁确保在同一时间只有一个节点能获得对共享资源的独占访问权限,从而解决并发访问问题。

Redisson锁(简称看门狗)

它可以实现锁的延长,确保某个线程执行完才能让其他线程进行抢锁操作

引入看门狗机制后

如何使用?

1、引入依赖包

<!--Redisson依赖-->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.31.0</version>
</dependency>

2、配置类Config

@Configuration //标明是配置类
public class RedissonConfiguration {
    /*注入到IOC容器中*/
    @Bean
    public RedissonClient redissonClient(){
        //1.创建配置对象
        Config config = new Config();
        // 集群模式
        //config.useClusterServers().addNodeAddress("集群ip1", "集群id2");
        //2.根据config创建出RedissonClient实例
          config.useSingleServer()
                .setAddress("redis://192.168.21.131:6379");
​
        //返回 RedissonClient实例
        return Redisson.create(config);
    }
}

3、编写Controller类

@RestController
@Slf4j
@RequestMapping("/api")
public class LockController {
    @Autowired
    private RedissonClient redissonClient;
​
    @PutMapping("/watch-dog")
    public String redissonLock() {
        RLock lock = redissonClient.getLock("anyLock");
            try {
                //尝试获取锁,tryLock参数分别是:获取锁的最大等待时间(期间重试) ,锁自动释放时间,时间单位
​
                //锁的获取时间(重试获得锁)为5秒,超过时间线程未结束会延长锁的获取时间,其他线程无法获得锁
                //boolean isLocked = lock.tryLock(5,10, TimeUnit.SECONDS);
                //不指定锁超时时间,锁会无限续期,直到获得锁的业务逻辑失败
                boolean isLocked = lock.tryLock(5, TimeUnit.SECONDS);
​
                if (isLocked) {
                    log.info("获取锁成功"+Thread.currentThread().getName()+":开始睡觉");
                        Thread.sleep(5*1000);
                    log.info("获取锁成功"+Thread.currentThread().getName()+":睡5秒,");
​
                    // 业务逻辑
                    Thread.sleep(10*1000);
                log.info("获取锁成功"+Thread.currentThread().getName()+":睡眠10秒,超过请求获取锁的时间");
                } else {
                    log.info("锁未释放{}获取锁失败",Thread.currentThread().getName());
                    return "无法获取锁";
                }
​
            } catch (InterruptedException e) {
                e.printStackTrace();
                return "线程被中断";
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
​
        return Thread.currentThread().getName();
    }
}
​
​

4、代码效果

避雷点

关于finallly释放锁时的踩雷点

直接lock.unlock会导致Redisson抛出异常,这个异常的原因是因为,当多个请求进来时,由于一个线程在占用着锁,其他线程无法获得锁,他就会走到finally中,去释放锁,但是由于它本身不带锁,就会触发异常。

解决办法

在释放之前添加if判断

finally{
    if(lock.isHeldByCurrenThread()){
        lock.unlock();  
    }
}
lock.isHeldByCurrenThread(),用于判断当前锁是否是当`前线程持有的,如果是就释放锁,不是就不让它释放,可以避免线程抛出异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这孩子叫逆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值