Redisson读写锁和分布式锁详解

锁的介绍

分布式锁是一种排他锁,在分布式情况下只有一个线程(一台机器)能够抢到锁。
读写锁是一种互斥锁,里面分为读锁和写锁,读锁和读锁不互斥,读锁和写锁互斥,写锁和写锁也互斥。

使用场景

当系统的两个地方使用同一份数据的时候,并且不能同时使用时可以加一个读写锁进行阻塞,如刷新缓存的时候不允许使用缓存,使用的时候不允许刷新。
分布式锁可以在多个线程(机器)同时使用同一资源时使用,比如启动初始化,多集群只要有一台机器初始化即可。

案例测试

现在模拟一种场景,项目启动时让一台机器去初始化缓存,其他机器不再重复刷新。此时可以通过分布式锁的lock.tryLock(); 进行尝试获取锁,若获取不到则说明其他机器正在刷新缓存,可以不处理,如果拿的到则加锁进行刷新,刷新完释放锁。
而此时假设有多个定时任务需要使用缓存数据,为了保持刷新缓存和读取缓存不相互影响,可以加个读写锁来控制,此时使用wLock.lock();rLock.lock(); 进行加锁,达到阻塞的作用。

tryLock()方法是尝试获取锁,返回一个true或者false,拿不到锁不进行阻塞。
lock()方法是尝试获取锁,拿不到锁进行阻塞,等待锁的释放再尝试抢占锁。

先看下测试代码

public void testLock() throws InterruptedException {
        String lockKey = "INIT_CACHE_LOCK";
        Lock lock = rdfaDistributeLockFactory.getLock(lockKey);

        RReadWriteLock readWriteLock = readWriteLockUtil.getReadWriteLock();
        RLock rLock = readWriteLock.readLock();
        RLock wLock = readWriteLock.writeLock();
        log.info("说明:两个分布式锁之间只有一个写锁的起终,写锁的起终之间不能有其他写锁和读锁,同一线程任意读锁起终之间不能有其他写锁,但允许有其他读锁。注:读锁和写锁抢不到阻塞,分布式锁抢不到则不处理。");
        log.info("-------------------------------------------------------------------------分割线-------------------------------------------------------------------------");
        for (int i = 0; i < 10; i++) {
            TimeUnit.SECONDS.sleep(5);
            new Thread(() -> {
                if (lock.tryLock()) {
                    log.info("当前线程:" + Thread.currentThread().getName() + "初始化程序抢到分布式锁------------------------------------------分布式锁-起");
                    try {
                        wLock.lock();
                        log.info("当前线程:" + Thread.currentThread().getName() + "初始化程序抢到写锁=============================================写锁-起");
                        TimeUnit.SECONDS.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        log.info("当前线程:" + Thread.currentThread().getName() + "初始化程序释放写锁============================================写锁-终");
                        wLock.unlock();
                        log.info("当前线程:" + Thread.currentThread().getName() + "初始化程序释放分布式锁锁---------------------------------------分布式锁-终");
                        lock.unlock();
                    }
                } else {
                    log.info("当前线程:" + Thread.currentThread().getName() + "缓存初始化正在进行中,当前机器不处理!^^^^^^^^^^^^^^^^^^^^^^^^^^^未抢到分布式锁-不处理");
                }
            }).start();
            TimeUnit.SECONDS.sleep(1);
            new Thread(() -> {
                try {
                    rLock.lock();
                    log.info("当前线程:" + Thread.currentThread().getName() + "定时任务抢到读锁**********************************************读锁-起");
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    log.info("当前线程:" + Thread.currentThread().getName() + "定时任务释放读锁**********************************************读锁-终");
                    rLock.unlock();
                }
            }).start();
        }
        TimeUnit.SECONDS.sleep(15);
        log.info("-------------------------------------------------------------------------分割线-------------------------------------------------------------------------");
    }

执行结果如下

 说明:两个分布式锁之间只有一个写锁的起终,写锁的起终之间不能有其他写锁和读锁,同一线程任意读锁起终之间不能有其他写锁,但允许有其他读锁。注:读锁和写锁抢不到阻塞,分布式锁抢不到则不处理。
 -------------------------------------------------------------------------分割线-------------------------------------------------------------------------
 当前线程:Thread-66初始化程序抢到分布式锁----------------------------------------分布式锁-起
 当前线程:Thread-66初始化程序抢到写锁============================================写锁-起
 redisson unlock redlock:org.redisson.RedissonLock@1ead4a6c
 当前线程:Thread-68缓存初始化正在进行中,当前机器不处理!^^^^^^^^^^^^^^^^^^^^^^^^^^未抢到分布式锁-不处理
 当前线程:Thread-66初始化程序释放写锁============================================写锁-终
 当前线程:Thread-66初始化程序释放分布式锁锁--------------------------------------分布式锁-终
 redission lock unlocked sucess:uds-calculate:INIT_CACHE_LOCK
 当前线程:Thread-67定时任务抢到读锁**********************************************读锁-起
 当前线程:Thread-70初始化程序抢到分布式锁----------------------------------------分布式锁-起
 当前线程:Thread-71定时任务抢到读锁**********************************************读锁-起
 当前线程:Thread-67定时任务释放读锁**********************************************读锁-终
 当前线程:Thread-71定时任务释放读锁**********************************************读锁-终
 当前线程:Thread-69定时任务抢到读锁**********************************************读锁-起
 redisson unlock redlock:org.redisson.RedissonLock@1ead4a6c
 当前线程:Thread-72缓存初始化正在进行中,当前机器不处理!^^^^^^^^^^^^^^^^^^^^^^^^^^未抢到分布式锁-不处理
 当前线程:Thread-73定时任务抢到读锁**********************************************读锁-起
 当前线程:Thread-69定时任务释放读锁**********************************************读锁-终
 当前线程:Thread-73定时任务释放读锁**********************************************读锁-终
 当前线程:Thread-70初始化程序抢到写锁============================================写锁-起
 redisson unlock redlock:org.redisson.RedissonLock@1ead4a6c
 当前线程:Thread-74缓存初始化正在进行中,当前机器不处理!^^^^^^^^^^^^^^^^^^^^^^^^^^未抢到分布式锁-不处理
 redisson unlock redlock:org.redisson.RedissonLock@1ead4a6c
 当前线程:Thread-76缓存初始化正在进行中,当前机器不处理!^^^^^^^^^^^^^^^^^^^^^^^^^^未抢到分布式锁-不处理
 当前线程:Thread-70初始化程序释放写锁============================================写锁-终
 当前线程:Thread-70初始化程序释放分布式锁锁--------------------------------------分布式锁-终
 redission lock unlocked sucess:uds-calculate:INIT_CACHE_LOCK
 当前线程:Thread-75定时任务抢到读锁**********************************************读锁-起
 当前线程:Thread-75定时任务释放读锁**********************************************读锁-终
 当前线程:Thread-77定时任务抢到读锁**********************************************读锁-起
 当前线程:Thread-78初始化程序抢到分布式锁----------------------------------------分布式锁-起
 当前线程:Thread-79定时任务抢到读锁**********************************************读锁-起
 当前线程:Thread-77定时任务释放读锁**********************************************读锁-终
 当前线程:Thread-79定时任务释放读锁**********************************************读锁-终
 当前线程:Thread-78初始化程序抢到写锁============================================写锁-起
 redisson unlock redlock:org.redisson.RedissonLock@1ead4a6c
 当前线程:Thread-80缓存初始化正在进行中,当前机器不处理!^^^^^^^^^^^^^^^^^^^^^^^^^^未抢到分布式锁-不处理
 redisson unlock redlock:org.redisson.RedissonLock@1ead4a6c
 当前线程:Thread-82缓存初始化正在进行中,当前机器不处理!^^^^^^^^^^^^^^^^^^^^^^^^^^未抢到分布式锁-不处理
 当前线程:Thread-78初始化程序释放写锁============================================写锁-终
 当前线程:Thread-78初始化程序释放分布式锁锁---------------------------------------分布式锁-终
 当前线程:Thread-81定时任务抢到读锁**********************************************读锁-起
 redission lock unlocked sucess:uds-calculate:INIT_CACHE_LOCK
 当前线程:Thread-81定时任务释放读锁**********************************************读锁-终
 当前线程:Thread-83定时任务抢到读锁**********************************************读锁-起
 当前线程:Thread-84初始化程序抢到分布式锁-----------------------------------------分布式锁-起
 当前线程:Thread-85定时任务抢到读锁**********************************************读锁-起
 当前线程:Thread-83定时任务释放读锁**********************************************读锁-终
 当前线程:Thread-85定时任务释放读锁**********************************************读锁-终
 当前线程:Thread-84初始化程序抢到写锁============================================写锁-起
 当前线程:Thread-84初始化程序释放写锁============================================写锁-终
 当前线程:Thread-84初始化程序释放分布式锁锁--------------------------------------分布式锁-终
 redission lock unlocked sucess:uds-calculate:INIT_CACHE_LOCK
 -------------------------------------------------------------------------分割线-------------------------------------------------------------------------

由以上测试案例可以看出分布式锁是排他锁,读写锁是互斥锁,且
读-读不互斥
读-写互斥
写-写互斥

你可能感兴趣的:(分布式,java,开发语言)