常见用法
RLock lock = redisson.getLock("anyLock"); try{ // 1. 最常见的使用方法 //lock.lock(); // 2. 支持过期解锁功能,10秒钟以后自动解锁, 无需调用unlock方法手动解锁 //lock.lock(10, TimeUnit.SECONDS); // 3. 尝试加锁,最多等待3秒,上锁以后10秒自动解锁 boolean res = lock.tryLock(3, 10, TimeUnit.SECONDS); if(res){ //成功 // do your business } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } |
参数含义
lock.tryLock(long waitTime, long leaseTime, TimeUnit unit)
前两个参数分别是等待锁时间、超时自动释放时间
坑一
超时施放时间
就是说 A拿到了锁之后, 如果发生了一些异常错误,内部业务没能正常的执行,没能正常执行释放锁的操作,这个时候这个超时施放时间才会起作用,也就是说,在A抢到锁之后,即便A的业务出现了堵塞,但是只要没发生一些异常情况,这里的超时施放时间是不起作用的,因为只要不发生异常,内部就会有一个 看门狗,每隔 超时施放时间/3就会刷新一次锁的过期时间(是一个定时任务),确保A能够执行完成业务,当然,A执行完业务后,会删除刷新有效期的定时任务。所以说,超时释放时间在正常执行业务的时候,是不发挥作用的,只在出现异常的时候才会起作用。
坑二
锁释放
常见用法中,会导致锁被其他线程释放。正常线程一持有锁,线程二在等待时间内未获取到锁,会先走到finally语句中,把当前的锁释放掉,然后return。如果再有线程三进来,发现锁已经被释放了,但是线程一还在执行,就会导致并发问题,所以正确的用法是应该判断当前线程是不是锁的持有者,再释放。
正确示例
RLock lock = redisson.getLock("anyLock"); try{ // 1. 最常见的使用方法 //lock.lock(); // 2. 支持过期解锁功能,10秒钟以后自动解锁, 无需调用unlock方法手动解锁 //lock.lock(10, TimeUnit.SECONDS); // 3. 尝试加锁,最多等待3秒,上锁以后10秒自动解锁 boolean res = lock.tryLock(3, 10, TimeUnit.SECONDS); if(res){ //成功 // do your business } } catch (InterruptedException e) { e.printStackTrace(); } finally { if (lock.isHeldByCurrentThread() && lock.isLocked()) { lock.unlock(); } } |