Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redisson release lock from different threads

I'm trying to create an infrastructure where different machines acquire shared locks through Redisson. Once the lock is acquired, some async tasks gets done, finally, when I finish the job, I'm releasing the Redisson lock through the thread currently running - but i receive the following error

java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: xxxxx thread-id: 57

So, I understand the meaning of that, but since I want to perform asynchronous work, I cannot use the acquiring thread to perform the release.

Should I not use Redisson locks? What is the best match for async work like that?

like image 463
Aviv Carmi Avatar asked May 22 '16 13:05

Aviv Carmi


4 Answers

As zapl mentioned, Java documentation shows that this is the proper behavior of a java lock. After discussing the issue on Reddison's GitHub page, it seems like Redisson Lock was not designed for that, and that the Redisson Semaphore will support async operations soon.

At the meantime, i plan to allocate a single thread to perform ALL locking and unlocking. Since Redisson has the support for async, non-blocking calls, this solution seems reasonable for now.

like image 70
Aviv Carmi Avatar answered Nov 06 '22 15:11

Aviv Carmi


I would recommend to use Redisson Semaphore object. Since 2.2.14 version it supports asynchronous operations via RSemaphoreAsync interface.

like image 42
Nikita Koksharov Avatar answered Nov 06 '22 13:11

Nikita Koksharov


Since your service is running on multiple nodes. Would suggest you to use lock.isHeldByCurrentThread() method before unlocking. A sample method would like

RLock lock = redissonClient().getLock(lockLabel);
try {
  if (lock.tryLock(lockAcquireWaitTime, lockLeaseTime, TimeUnit.MINUTES)) {
   //Action to be performed when lock is acquired.
    lock.unlock();
  }
  Thread.sleep(syncMonitorInterval);
} catch (Exception e) {
  LOG.error("Error..", e);
} finally {
  if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
    lock.unlock();
    LOG.debug("lock released");
  }
}
like image 1
Srijan Mehrotra Avatar answered Nov 06 '22 14:11

Srijan Mehrotra


I use forceUnlock() instead of unlock(), it works and successfully release the lock locked by another thread, but may be not a recommanded way.

Another way please refer to https://github.com/redisson/redisson/issues/2224 you can use lockAsync(threadId) and unlockAsync(threadId) to walk around the thread id check.

like image 1
Rocky Tu Avatar answered Nov 06 '22 15:11

Rocky Tu