redisson使用

环境搭建

导入pom包

       <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.16.8</version>
        </dependency>

创建redisson客户端

根据文档提示
image
不过这个锁多节点redis 往下翻有个单节点redis配置的
image
将reddisson客户端注入到spring容器即可

@Configuration
public class RedissonConfig {
    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient() {

        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("990728");
        return Redisson.create(config);
    }
}

可重用锁

介绍

可以重用锁是 当一个被锁线程调用内层方法 内层方法自动获取线程锁 可以避免死锁

redisson中使用

redssion中的可重用锁是非阻塞式等待的 只有上一个业务方法执行完毕 下一个线程才可以获取到锁
redisson引入了看门狗机制 若业务未执行完毕 将会自动进行续期
若抛出异常或服务器发生了宕机 redis中加锁数据也会设置过失效时间而会被自动删除 并不会发生死锁

    public String sayHello() {
        // 获取一啊锁
        RLock lock = redissonClient.getLock("my-lock");

        lock.lock();
        System.out.println("加锁成功--------" + Thread.currentThread().getId());

        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("解锁成功--------" + Thread.currentThread().getId());
            lock.unlock();
        }

        return "Hello world";
    }

看门狗机制原理

lock.lock(2000, TimeUnit.SECONDS); 将不会启动看门狗机制 会执行lua脚本设置redis的失效时间
若不传入失效时间 则redisson 会设置失效时间为30s 还会启动一个定时任务 每过10s进行自动续期(30 / 3)

最佳使用实践

我们可以不用看门狗机制 直接指定超时时间 比如设置为30s 30s内业务没执行完成表示业务出问题了
计算不进行解锁30s 会执行finally语句 会自动对锁进行解锁

读写锁

只要将写锁释放才能进行读操作
读 + 读: 无锁状态 都可以读
读 + 写: 读操作完毕 才能进行写操作
写 + 读: 写操作完毕才能进行读
写 + 写: 阻塞 一个写万 另一个才能进行写

文档是这样写的
image
readLock为读锁 writeLock为写锁 只要锁的名称相同就表示是同一把锁

    @GetMapping("/read")
    @ResponseBody
    public String read() {
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("rd-lock");
        // 获取读锁
        RLock rLock = readWriteLock.readLock();

        String s = null;

        try {
            rLock.lock();
            System.out.println("read 上锁");
            s = redisTemplate.opsForValue().get("writeValue");
            Thread.sleep(30000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("read 解锁");
            rLock.unlock();
        }

        return s;
    }

    @GetMapping("/write")
    @ResponseBody
    public String write() {
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("rd-lock");

        // 获取写锁
        RLock writeLock = readWriteLock.writeLock();

        String s = UUID.randomUUID().toString();

        try {
            writeLock.lock();
            System.out.println("write 上锁");
            redisTemplate.opsForValue().set("writeValue", s);
            Thread.sleep(30000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("write 解锁");
            writeLock.unlock();
        }

        return s;
    }

信号量

类似操作系统中的PV操作
有一个生产者 一个消费者 若没有资源 则消费者会无限期阻塞 直到生产者生产数据
image
使用getSemaphore获取一个信号量 信号量的名字相同表示同一个信号量
acquire消费
release生产

    @GetMapping("/p")
    @ResponseBody
    public String p() {
        RSemaphore pv = redissonClient.getSemaphore("pv");

        try {
            pv.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return "ok";
    }

    @GetMapping("/v")
    @ResponseBody
    public String v() {
        RSemaphore pv = redissonClient.getSemaphore("pv");

        pv.release();

        return "ok";
    }

闭锁

只有计数器的值为0才能执行

    // 闭锁 所有操作完成才能进行闭锁操作
    @GetMapping("/lockDoor")
    @ResponseBody
    public String lockDoor() throws InterruptedException {
        // 获取一个闭锁
        RCountDownLatch downLock = redissonClient.getCountDownLatch("downLock");
        // 设置计数器的值
        downLock.trySetCount(5);

        downLock.await();

        return "lock door";
    }

    @GetMapping("/gogogo")
    @ResponseBody
    public String go() {
        RCountDownLatch downLock = redissonClient.getCountDownLatch("downLock");
        // 计数器 - 1
        downLock.countDown();

        return "go";
    }
posted @   RainbowMagic  阅读(707)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示