基于Redis的Redisson分布式可重入锁实现了
java.util.concurrent.locks.Lock
接口
Redisson 锁的种类有以下几种:可重入锁,公平锁,联锁,红锁,读写锁,接下来我们详细介绍一下每一种锁。
- 可重入锁
一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接执行调用的方法,而无需重新获得锁。
public void method1() { RLock lock = redissonClient.getLock("lock"); try { lock.lock(); method2(); } finally { lock.unlock(); } System.out.println("释放锁成功"); } public void method2() { RLock lock = redissonClient.getLock("lock"); try { if (lock.tryLock()) { System.out.println("加锁成功"); //业务逻辑 } } finally { lock.unlock(); } }
- 公平锁
它保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程。所有请求线程会在一个队列中排队,当某个线程出现宕机时,Redisson会等待5秒后继续下一个线程,也就是说如果前面有5个线程都处于等待状态,那么后面的线程会等待至少25秒。
RLock fairLock = redisson.getFairLock("anyLock"); // 最常见的使用方法 fairLock.lock();
- 联锁
可以将多个锁对象关联到一个锁对象时
-
RLock lock1 = redissonInstance1.getLock("lock1"); RLock lock2 = redissonInstance2.getLock("lock2"); RLock lock3 = redissonInstance3.getLock("lock3"); RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3); // 同时加锁:lock1 lock2 lock3 // 所有的锁都上锁成功才算成功。 lock.lock(); //业务逻辑 lock.unlock();
- 红锁
当有大部分(一半以上)锁加锁成功后,才算真正获得锁
RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");
RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 同时加锁:lock1 lock2 lock3
// 红锁在大部分节点上加锁成功就算成功。 这里有3个锁,至少2个加锁成功,才算真的加锁成功
lock.lock();
...
lock.unlock();
- 读写锁
上读锁的时候可以多个线程获取,上写锁只能有一个线程获取,经过测试当写锁还未释放的时候,读锁阻塞获取不了,直到写锁释放。
/**
* 保证一定能读到最新数据,修改期间,写锁是一个排他锁(互斥锁)。读锁是一个共享锁
* 写锁没释放,读就必须等待
*/
@GetMapping("/read")
@ResponseBody
public String readValue() {
RReadWriteLock readWriteLock = redisson.getReadWriteLock("rw-lock");
RLock rLock = readWriteLock.readLock();
try {
rLock.lock();
} catch (Exception e) {
e.printStackTrace();
} finally {
rLock.unlock();
}
return "";
}
@GetMapping("/write")
@ResponseBody
public String writeValue() {
RReadWriteLock readWriteLock = redisson.getReadWriteLock("rw-lock");
RLock rLock = readWriteLock.writeLock();
try {
//1、改数据加写锁,读数据加读锁
rLock.lock();
TimeUnit.SECONDS.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
rLock.unlock();
}
return "";
}