redisson使用
环境搭建
导入pom包
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.16.8</version>
</dependency>
创建redisson客户端
根据文档提示
不过这个锁多节点redis 往下翻有个单节点redis配置的
将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语句 会自动对锁进行解锁
读写锁
只要将写锁释放才能进行读操作
读 + 读: 无锁状态 都可以读
读 + 写: 读操作完毕 才能进行写操作
写 + 读: 写操作完毕才能进行读
写 + 写: 阻塞 一个写万 另一个才能进行写
文档是这样写的
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操作
有一个生产者 一个消费者 若没有资源 则消费者会无限期阻塞 直到生产者生产数据
使用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";
}
虽然道路是曲折的,但前途是光明的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律