分布式锁是一种排他锁,在分布式情况下只有一个线程(一台机器)能够抢到锁。
读写锁是一种互斥锁,里面分为读锁和写锁,读锁和读锁不互斥,读锁和写锁互斥,写锁和写锁也互斥。
当系统的两个地方使用同一份数据的时候,并且不能同时使用时可以加一个读写锁进行阻塞,如刷新缓存的时候不允许使用缓存,使用的时候不允许刷新。
分布式锁可以在多个线程(机器)同时使用同一资源时使用,比如启动初始化,多集群只要有一台机器初始化即可。
现在模拟一种场景,项目启动时让一台机器去初始化缓存,其他机器不再重复刷新。此时可以通过分布式锁的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
-------------------------------------------------------------------------分割线-------------------------------------------------------------------------
由以上测试案例可以看出分布式锁是排他锁,读写锁是互斥锁,且
读-读不互斥
读-写互斥
写-写互斥