Redis的Redisson库的API方法.unlock()没有释放锁,在尝试使用相同实例解锁。

huangapple go评论116阅读模式
英文:

Redis's Redisson's API method .unlock() is not releasing the lock, trying from the same instance

问题

我在我的Java应用程序中创建了一个单例的Redisson实例,我使用它来与Redis服务器进行通信。
现在,使用这个Redisson实例,我正在获取一个锁,在完成一些任务后,我会释放它。但是在调用unlock方法之后,我仍然看到Redis仍然持有该锁,其他线程无法获取该锁。
以下是我正在使用的代码片段:

  1. class RedisInstance
  2. {
  3. static RedisInstance ins;
  4. private RedisInstance()
  5. {
  6. ins = new RedisInstance();
  7. }
  8. public static RedisInstance getInstance()
  9. {
  10. return ins;
  11. }
  12. //获取锁:
  13. public boolean acquireLock(String lockKey)
  14. {
  15. RLock redisLock = getRedisClient().getLock(lockKey);
  16. boolean isLockFree;
  17. try
  18. {
  19. isLockFree = redisLock.tryLock(lockAcquistionTimeLimit, TimeUnit.SECONDS);
  20. if(isLockFree)
  21. {
  22. redisLock.lock();
  23. logger.info("锁已获取:{}", lockKey);
  24. return true;
  25. }
  26. }
  27. catch (InterruptedException e)
  28. {
  29. logger.error("在获取Redis锁时发生异常:{}", e, lockKey);
  30. }
  31. return false;
  32. }
  33. //释放锁:
  34. public void unlock(String lockKey)
  35. {
  36. RLock redisLock = getRedisClient().getLock(lockKey);
  37. redisLock.unlock();
  38. logger.debug("Redis是否已锁定:" + redisLock.isLocked());
  39. logger.info("锁已释放:{}", lockKey);
  40. }
  41. }
  1. class A
  2. {
  3. RedisIns ins = RedisInstance.getInstance();
  4. public void run()
  5. {
  6. if(ins.acquireLock(lockKey))
  7. {
  8. try
  9. {
  10. //进行一些处理,耗时不到一秒
  11. }
  12. catch(Exception e)
  13. {
  14. }
  15. finally
  16. {
  17. ins.unlock(lockKey);
  18. }
  19. }
  20. }
  21. //在我的主方法中:
  22. public static void main(String args[])
  23. {
  24. A a = new A();
  25. A b = new A();
  26. Thread t1 = new Thread(a);
  27. Thread t2 = new Thread(b);
  28. t1.start();
  29. Thread.sleep(5000); //仅为模拟,假设t1在t2开始之前完成
  30. t2.start();
  31. }
  32. }

在t1调用ins.unlock(lockKey);之后,日志logger.debug("Redis是否已锁定:" + redisLock.isLocked());显示为:true,且t2无法获取锁。

但是,如果我将redisLock.unlock();替换为redisLock.forceUnlock();,一切都按预期工作。不知道为什么unlock()无法释放锁,而forceUnlock()可以。

英文:

I have created singleton redisson instance in my Java application, which I am using to communicate to redis servers.
Now using this redisson instance, I am acquiring a lock which after getting some task done, I am releasing. But after calling unlock method, I still see redis have the lock and other threads are unable to acquire the lock.
Below is the code snippet, I am using:

  1. class RedisInstance
  2. {
  3. static RedisInstance ins;
  4. private RedisInstance()
  5. {
  6. ins = new RedisInstance();
  7. }
  8. public static RedisInstance getInstance()
  9. {
  10. return ins;
  11. }
  12. //Acquire the lock:
  13. public boolean acquireLock(String lockKey)
  14. {
  15. RLock redisLock = getRedisClient().getLock(lockKey);
  16. boolean isLockFree;
  17. try
  18. {
  19. isLockFree = redisLock.tryLock(lockAcquistionTimeLimit, TimeUnit.SECONDS);
  20. if(isLockFree)
  21. {
  22. redisLock.lock();
  23. logger.info("lock acquired for: {}", lockKey);
  24. return true;
  25. }
  26. }
  27. catch (InterruptedException e)
  28. {
  29. logger.error("Got exception {} in acquiring Redis Lock for: {}" , e, lockKey);
  30. }
  31. return false;
  32. }
  33. //Release the lock:
  34. public void unlock(String lockKey)
  35. {
  36. RLock redisLock = getRedisClient().getLock(lockKey);
  37. redisLock.unlock();
  38. logger.debug("IS redis locked "+redisLock.isLocked());
  39. logger.info("lock released for: {}", lockKey);
  40. }
  41. }
  1. class A
  2. {
  3. RedisIns ins = RedisInstance.getInstance();
  4. public void run()
  5. {
  6. if(ins.acquireLock(lockKey))
  7. {
  8. try
  9. {
  10. //do some processing takes less than a second
  11. }
  12. catch(Exception e)
  13. {
  14. }
  15. finally
  16. {
  17. ins.unlock(lockKey);
  18. }
  19. }
  20. }
  21. //In my main method:
  22. public static void main(String args[])
  23. {
  24. A a = new A();
  25. A b = new A();
  26. Thread t1 = new Thread(a);
  27. Thread t2 = new Thread(b);
  28. t1.start();
  29. Thread.sleep(5000); //just to mock, lets say t1 finishes before t2 starts
  30. t2.start();
  31. }
  32. }

After t1 calls ins.unlock(lockKey);, the log logger.debug("IS redis locked "+redisLock.isLocked()); says: true and t2 is unable to acquire the lock.

But if I replace redisLock.unlock(); with redisLock.forceUnlock(); everything is working as expected.
Dont know why unlock() is unable to release the lock forceUnlock() is able to do it.

答案1

得分: 1

tryLock如果成功获取了锁,则返回true。因此,在此之后调用lock是不必要的,我认为这可能是您问题的原因。实现可能期望锁定/解锁成对出现,而在您的情况下,lock的次数比unlock多一个。

英文:

tryLock returns true if it acquired the lock. So calling lock after is unnecessary, and I think it may be the cause of your problem. The implementation probably expects an even number of lock/unlock and in you case you have one more lock than unlock.

huangapple
  • 本文由 发表于 2020年9月11日 09:40:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/63839691.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定