redisson锁 tryLock的正确用法
1.现在错误的用法:
RLock lock = redisson.getLock(String.format(LOCK_KEY, 2)); try { if (lock.tryLock()) { //处理 logger.info("aaaaaaaaaaaaaaaaaa"); } catch(Exception e) { //处理异常 } finally { if (lock.isLocked()) { lock.unlock(); } }
测试实例:
TwoThread.java
public class TwoThread implements Runnable { private RedissonClient redisson; public TwoThread(RedissonClient redisson) { this.redisson = redisson; } private Logger logger = LogManager.getLogger(getClass()); private String REWARD_CARD_LOCK_KEY = "444:lock:%d"; public void run() { RLock lock = redisson.getLock(String.format(REWARD_CARD_LOCK_KEY, 2)); logger.info("thread---{}, lock:{}",Thread.currentThread().getId(), lock); try { if (lock.tryLock()) { logger.info("tryLock thread---{}, lock:{}",Thread.currentThread().getId(),lock); logger.info("aaaaaaaaaaaaaaaaaa"); } } finally { boolean locked = lock.isLocked(); logger.info("thread---{},lock:{},locked:{}",Thread.currentThread().getId(),lock,locked); if (locked) { logger.info("thread unlock---{}, lock:{}",Thread.currentThread().getId(),lock); lock.unlock(); } } }
测试类:
Thread one = new Thread(new TwoThread(redisson)); Thread two = new Thread(new TwoThread(redisson)); Thread three = new Thread(new TwoThread(redisson)); Thread four = new Thread(new TwoThread(redisson)); one.start(); two.start(); three.start(); four.start();
打印结果:
thread---111, lock:org.redisson.RedissonLock@1cb2393f thread---112, lock:org.redisson.RedissonLock@70feb82b thread---114, lock:org.redisson.RedissonLock@50384a5d thread---113, lock:org.redisson.RedissonLock@42232129 thread---111,lock:org.redisson.RedissonLock@1cb2393f,locked:true aaaaaaaaaaaaaaaaaa thread---113,lock:org.redisson.RedissonLock@42232129,locked:true thread---112,lock:org.redisson.RedissonLock@70feb82b,locked:true thread unlock---111, lock:org.redisson.RedissonLock@1cb2393f thread---114,lock:org.redisson.RedissonLock@50384a5d,locked:true thread unlock---114, lock:org.redisson.RedissonLock@50384a5d thread unlock---113, lock:org.redisson.RedissonLock@42232129 thread unlock---112, lock:org.redisson.RedissonLock@70feb82b Exception in thread "Thread-20" Exception in thread "Thread-19" java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: 54882863-3389-40e7-ba4d-58ecae0a7155 thread-id: 114 at org.redisson.RedissonLock.unlock(RedissonLock.java:367) at xx.TwoThread.run(TwoThread.java:36) at java.lang.Thread.run(Thread.java:745) java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: 54882863-3389-40e7-ba4d-58ecae0a7155 thread-id: 113 at org.redisson.RedissonLock.unlock(RedissonLock.java:367) at xx.TwoThread.run(TwoThread.java:36) at java.lang.Thread.run(Thread.java:745)
尝试去解锁,但是没有被当前线程锁住。
boolean locked = lock.isLocked()为什么一直返回true,查看源码,只要这个锁被任意一个线程锁,就会返回true
/** * Checks if this lock locked by any thread * * @return <code>true</code> if locked otherwise <code>false</code> */ boolean isLocked();
所以,在finally里面 没有被锁就解锁,肯定会报错的。
2.tryLock正确用法:
RLock lock = redisson.getLock(String.format(REWARD_CARD_LOCK_KEY, 2)); try { //尝试加锁,最多等待10秒,上锁以后10秒自动解锁 if (lock.tryLock(10,10, TimeUnit.SECONDS)) { try { //处理 logger.info("tryLock thread---{}, lock:{}", Thread.currentThread().getId(), lock); } catch (Exception e) { } finally { //解锁 lock.unlock(); } } } catch (InterruptedException e) { //处理 //保留中断发生的证据,以便调用栈中更高层的代码能知道中断,并对中断作出响应 Thread.currentThread().interrupt(); }
关于处理InterruptedException,文档参考:
需要恢复中断状态场景的一个例子,方便理解: