Redisson分布式锁解锁异常问题
作者:知知之之
文章主要描述了在使用Redisson进行分布式锁操作时,遇到的`IllegalMonitorStateException`异常,通过分析报错信息,作者发现了问题的根源在于线程尝试解锁但未按顺序执行,作者提出了两种解决方案:在解锁前增加判断,确保线程已获得锁
问题现象
程序中的redission执行unlock()报错如下:
java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id:
从报错信息可知:尝试解锁,而不是由当前线程按节点 ID 锁定
问题复现
//获取锁对象 RLock lock = redissonClient.getLock(key); try{ //获取锁 boolean tryLock = lock.tryLock(5, TimeUnit.SECONDS); if (!tryLock) { //抛出业务异常 } }catch(){ //捕获异常 }finally{ //解锁 lock.unlock(); }
排查过程
如上代码,线程无论是否有获取锁,都是需要去执行解锁方法,当线程没有获得锁,执行unlock()就会报
java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id:错误
解决方案
1、在解锁时增加判断
//判断要解锁的key是否已被锁定;判断要解锁的key是否被当前线程持有 if (lock.isLocked() && lock.isHeldByCurrentThread()) { lock.unlock(); }
2、优化代码
在执行unlock()确保线程已经获得锁
//获取锁对象 RLock lock = redissonClient.getLock(key); boolean tryLock; try { tryLock = lock.tryLock(5, TimeUnit.SECONDS); } catch (InterruptedException e) { throw new Exception("获取分布式锁失败,请稍后再试"); } if (!tryLock) { throw new Exception("请稍后再试"); } try{ //抛出业务异常 }catch(){ //捕获异常 }finally{ //解锁 lock.unlock(); }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。