likes
comments
collection
share

Redisson《二:读写锁》

作者站长头像
站长
· 阅读数 60

基于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值,启动项目测试

Redisson《二:读写锁》

先测试读锁,发现如果没有写锁,访问正常 Redisson《二:读写锁》 我们测试写锁,在写锁没释放之前,再访问读锁 Redisson《二:读写锁》 因为我们设置了30s的休眠时间,30s之前,写锁逻辑没执行完,读锁就会一直在等待,当写锁完成以后,读锁也会读到当前最新数据 Redisson《二:读写锁》

二:读写锁补充

2.1读+读

相当于无锁,并发读,只会在redis中记录好,所有当前的锁,都会同时加锁成功

2.2写+读

等待写锁释放

2.3写+写

阻塞等待

2.4读+写

有读锁,写也需要等待

总结就是一句话:只要有写的存在,都必须等待

转载自:https://juejin.cn/post/7000178450614976549
评论
请登录