Redisson《二:读写锁》
基于Redis的Redisson分布式可重入读写锁RReadWriteLock
Java对象实现了java.util.concurrent.locks.ReadWriteLock
接口。其中读锁和写锁都继承了RLock接口。
分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。
RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
// 最常见的使用方法
rwlock.readLock().lock();
// 或
rwlock.writeLock().lock();
如果负责储存这个分布式锁的Redis节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。
另外Redisson还通过加锁的方法提供了leaseTime
的参数来指定加锁的时间。超过这个时间后锁便自动解开了。
// 10秒钟以后自动解锁
// 无需调用unlock方法手动解锁
rwlock.readLock().lock(10, TimeUnit.SECONDS);
// 或
rwlock.writeLock().lock(10, TimeUnit.SECONDS);
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS);
// 或
boolean res = rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();
一:编写读写锁
1.1写锁代码示例如下
/**
* 测试写锁
* 作用:保证一定能读到最新数据,修改期间,写锁是一个排它锁(互斥锁)
*/
@GetMapping("/write")
@ResponseBody
public String writeLock(){
String s=null;
RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("readWriteLock");
//业务逻辑是写一个锁
readWriteLock.writeLock().lock();
try {
s = UUID.randomUUID().toString();
Thread.sleep(30000);
redisTemplate.opsForValue().set("writeValue",s);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
readWriteLock.writeLock().unlock();
}
return s;
}
1.2读锁代码示例如下
/**
* 测试读锁
* 读锁是一个共享锁(写锁没释放,读锁就会一直等待)
*/
@ResponseBody
@GetMapping("/read")
public String readLock(){
String writeValue=null;
RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("readWriteLock");
readWriteLock.readLock().lock();
try{
writeValue = redisTemplate.opsForValue().get("writeValue");
}catch (Exception e){
}finally {
readWriteLock.readLock().unlock();
}
return writeValue;
}
}
1.3在redis里先插入writeValue值,启动项目测试
先测试读锁,发现如果没有写锁,访问正常
我们测试写锁,在写锁没释放之前,再访问读锁
因为我们设置了30s的休眠时间,30s之前,写锁逻辑没执行完,读锁就会一直在等待,当写锁完成以后,读锁也会读到当前最新数据
二:读写锁补充
2.1读+读
相当于无锁,并发读,只会在redis中记录好,所有当前的锁,都会同时加锁成功
2.2写+读
等待写锁释放
2.3写+写
阻塞等待
2.4读+写
有读锁,写也需要等待
总结就是一句话:只要有写的存在,都必须等待
转载自:https://juejin.cn/post/7000178450614976549