失败无限重试- 多个线程竞争,第一个拿到锁第二个会无限重试
RLock lock = redisson.getLock("码哥字节");
try {
// 1.最常用的第一种写法
lock.lock();
// 执行业务逻辑
.....
} finally {
lock.unlock();
}
拿锁失败时会不停的重试,具有Watch Dog 自动延期机制,默认续30s 每隔30/3=10 秒续到30s。
watchDog 只有在未显示指定加锁超时时间(leaseTime)时才会生效。
失败超时重试,自动续命
// 第一次失败后,尝试拿锁10s后停止重试,获取失败返回false,具有Watch Dog 自动延期机制, 默认续30s 业务逻辑没执行完会自动续期
boolean flag = lock.tryLock(10, TimeUnit.SECONDS);
超时自动释放锁
// 没有Watch Dog ,10s后自动释放,不需要调用 unlock 释放锁。
lock.lock(10, TimeUnit.SECONDS);
超时重试,自动解锁
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁,没有 Watch dog
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
try {
...
} finally {
lock.unlock();
}
}
具体使用方法详见下面代码
public void lock() throws InterruptedException{
log.info("线程:{},进入方法",Thread.currentThread().getName());
RLock rLock = redissonClient.getLock("lock");
//加锁:锁的有效期默认30秒
rLock.lock();
long timeToLive = rLock.remainTimeToLive();
log.info("线程:{},获得锁,锁存活时间:{}S",Thread.currentThread().getName(),timeToLive/1000);
//休眠一下
Thread.sleep(2000);
//失败的线程会一直重试,直到获取成功
//如果主线程未释放,且当前锁未调用unlock方法,则进入到watchDog机制
//如果主线程未释放,且当前锁调用unlock方法,则直接释放锁
rLock.unlock();
log.info("线程:{},释放锁",Thread.currentThread().getName());
}
public void lockLaseTime() throws InterruptedException{
log.info("线程:{},进入方法",Thread.currentThread().getName());
RLock rLock = redissonClient.getLock("lockLaseTime");
//加锁 上面是默认30秒,
//这里可以手动设置锁的有效时间,锁到期后会自动释放的
rLock.lock(10,TimeUnit.SECONDS);
long timeToLive = rLock.remainTimeToLive();
log.info("线程:{},获得锁,锁存活时间:{}S",Thread.currentThread().getName(),timeToLive/1000);
//休眠一下
Thread.sleep(2000);
//设置了时间,没有watchdog机制
//如果主线程未释放,且当前锁未调用unlock方法,则锁到期后会自动释放的
//如果主线程未释放,且当前锁调用unlock方法,则直接释放锁
rLock.unlock();
log.info("线程:{},释放锁",Thread.currentThread().getName());
}
public void tryLock() throws InterruptedException {
log.info("线程:{},进入方法",Thread.currentThread().getName());
RLock rLock = redissonClient.getLock("tryLock");
//tryLock()方法是有返回值的,它表示用来尝试获取锁,
//如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false .
boolean flag = rLock.tryLock();
if (flag){
long timeToLive = rLock.remainTimeToLive();
log.info("线程:{},获得锁,锁存活时间:{}S,加锁状态:{}",Thread.currentThread().getName(),timeToLive/1000,flag);
//休眠一下
Thread.sleep(2000);
//一般情况下用这个也行,但是没有显示指定锁存在时间
//如果主线程未释放,且当前锁未调用unlock方法,则进入到watchDog机制
//如果主线程未释放,且当前锁调用unlock方法,则直接释放锁
rLock.unlock();
log.info("线程:{},释放锁",Thread.currentThread().getName());
}else {
log.info("线程:{},获得锁失败",Thread.currentThread().getName());
}
}
public void tryLockWaitTime() throws InterruptedException {
log.info("线程:{},进入方法",Thread.currentThread().getName());
RLock rLock = redissonClient.getLock("tryLockWaitTime");
//tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似的,
//只不过区别在于这个方法在拿不到锁时会等待一定的时间,
//在时间期限之内如果还拿不到锁,就返回false。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。
//这里的6是如果一个线程拿锁失败会在六秒内进行重试
boolean flag = rLock.tryLock(6, TimeUnit.SECONDS);
if (flag){
long timeToLive = rLock.remainTimeToLive();
log.info("线程:{},获得锁,锁存活时间:{}S,加锁状态:{}",Thread.currentThread().getName(),timeToLive/1000,flag);
//休眠一下
Thread.sleep(10000);
//如果主线程未释放,且当前锁未调用unlock方法,则进入到watchDog机制
//如果主线程未释放,且当前锁调用unlock方法,则直接释放锁
rLock.unlock();
log.info("线程:{},释放锁",Thread.currentThread().getName());
}else {
log.info("线程:{},获得锁失败",Thread.currentThread().getName());
}
}
public void tryLockleasTime() throws InterruptedException {
log.info("线程:{},进入方法",Thread.currentThread().getName());
RLock rLock = redissonClient.getLock("tryLockleasTime");
//比上面多一个参数,多添加一个锁的有效时间
//锁存在10秒,在11秒内,获取锁失败的线程都会重复的去获取锁,这里第一个参数也可以设置为0,失败就不获取了。
boolean flag = rLock.tryLock(11,10, TimeUnit.SECONDS);
if (flag){
long timeToLive = rLock.remainTimeToLive();
log.info("线程:{},获得锁,锁存活时间:{}S,加锁状态:{}",Thread.currentThread().getName(),timeToLive/1000,flag);
//休眠一下
Thread.sleep(6000);
//如果主线程未释放,且当前锁未调用unlock方法,则锁到期后会自动释放的
//如果主线程未释放,且当前锁调用unlock方法,则直接释放锁
rLock.unlock();
log.info("线程:{},释放锁",Thread.currentThread().getName());
}else {
log.info("线程:{},获得锁失败",Thread.currentThread().getName());
}
}