8. Distributed locks and synchronizers

Nikita Koksharov edited this page Jan 11, 2018 · 16 revisions

8.1. Lock

Redis based distributed reentrant Lock object for Java implements java.util.concurrent.locks.Lock interface.

RLock lock = redisson.getLock("anyLock");
// Most familiar locking method
lock.lock();

If Redis node which stores lock state crashes and lock has been already acquired then it could hang forever. To avoid this Redisson maintains lock watchdog, it prolongs lock expiration while lock holder Redisson instance is alive. By default lock watchdog timeout is 30 seconds and can be changed through Config.lockWatchdogTimeout setting.

Also Redisson allow to specify leaseTime parameter during lock acquisition. After specified time interval locked lock will be released automatically.

// Acquire lock and release it automatically after 10 seconds
// if unlock method hasn't been invoked
lock.lock(10, TimeUnit.SECONDS);

// Wait for 100 seconds and automatically unlock it after 10 seconds
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();

Redisson also provides an asynchronous methods for Lock object:

RLock lock = redisson.getLock("anyLock");
lock.lockAsync();
lock.lockAsync(10, TimeUnit.SECONDS);
Future<Boolean> res = lock.tryLockAsync(100, 10, TimeUnit.SECONDS);

RLock objects behave according java Lock specification. It means only lock owner thread can unlock it otherwise IllegalMonitorStateException would be thrown. But if you still need such scenario use RSemaphore object.

8.2. Fair Lock

Redis based distributed reentrant fair Lock object for Java implements java.util.concurrent.locks.Lock interface. It guarantees that Redisson client threads will acquire it in is same order they requested it.

RLock fairLock = redisson.getFairLock("anyLock");
// Most familiar locking method
fairLock.lock();

If Redis node which stores lock state crashes and lock has been already acquired then it could hang forever. To avoid this Redisson maintains lock watchdog, it prolongs lock expiration while lock holder Redisson instance is alive. By default lock watchdog timeout is 30 seconds and can be changed through Config.lockWatchdogTimeout setting.

Also Redisson allow to specify leaseTime parameter during lock acquisition. After specified time interval locked lock will be released automatically.

// Acquire lock and release it automatically after 10 seconds
// if unlock method hasn't been invoked
fairLock.lock(10, TimeUnit.SECONDS);

// Wait for 100 seconds and automatically unlock it after 10 seconds
boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS);
...
fairLock.unlock();

Redisson also provides an asynchronous methods for fair Lock object:

RLock fairLock = redisson.getFairLock("anyLock");
fairLock.lockAsync();
fairLock.lockAsync(10, TimeUnit.SECONDS);
Future<Boolean> res = fairLock.tryLockAsync(100, 10, TimeUnit.SECONDS);

8.3. MultiLock

Redis based distributed RedissonMultiLock object groups multiple RLock objects and handles them as one lock. Each RLock object may belong to different Redisson instances.

RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");

RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
// locks: lock1 lock2 lock3
lock.lock();
...
lock.unlock();

If Redis nodes stored lock state crash and multiple locks have been already acquired then they could hang forever. To avoid this Redisson maintains lock watchdog, it prolongs each lock expiration while lock holder Redisson instance is alive. By default lock watchdog timeout is 30 seconds and can be changed through Config.lockWatchdogTimeout setting.

Also Redisson allow to specify leaseTime parameter during lock acquisition. After specified time interval all locked locks will be released automatically.

RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
// Acquire lock1, lock2, lock3 and release it automatically after 10 seconds
// if unlock method hasn't been invoked
lock.lock(10, TimeUnit.SECONDS);

// Wait for 100 seconds and automatically unlock it after 10 seconds
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();

8.4. RedLock

Redis based distributed RedissonRedLock object implements Redlock locking algorithm. It groups multiple RLock objects and handles them as one lock. Each RLock object may belong to different Redisson instances.

RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");

RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// locks: lock1 lock2 lock3
lock.lock();
...
lock.unlock();

If Redis nodes stored lock state crash and multiple locks have been already acquired then they could hang forever. To avoid this Redisson maintains lock watchdog, it prolongs each lock expiration while lock holder Redisson instance is alive. By default lock watchdog timeout is 30 seconds and can be changed through Config.lockWatchdogTimeout setting.

Also Redisson allow to specify leaseTime parameter during lock acquisition. After specified time interval all locked locks will be released automatically.

RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// Acquire lock1, lock2, lock3 and release it automatically after 10 seconds
// if unlock method hasn't been invoked
lock.lock(10, TimeUnit.SECONDS);

// Wait for 100 seconds and automatically unlock it after 10 seconds
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();

8.5. ReadWriteLock

Redis based distributed reentrant ReadWriteLock object for Java implements java.util.concurrent.locks.ReadWriteLock interface and supports TTL. Many ReadLock owners and only one WriteLock owner are allowed.

RReadWriteLock rwlock = redisson.getLock("anyRWLock");
// Most familiar locking method
rwlock.readLock().lock();
// or
rwlock.writeLock().lock();

If Redis node stored lock state crashes and lock has been already acquired then it could hang forever. To avoid this Redisson maintains lock watchdog, it prolongs lock expiration while lock holder Redisson instance is alive. By default lock watchdog timeout is 30 seconds and can be changed through Config.lockWatchdogTimeout setting.

Also Redisson allow to specify leaseTime parameter during lock acquisition. After specified time interval locked lock will be released automatically.

// Acquire lock and release it automatically after 10 seconds
// if unlock method not invoked
rwlock.readLock().lock(10, TimeUnit.SECONDS);
// or
rwlock.writeLock().lock(10, TimeUnit.SECONDS);

// Wait for 100 seconds and automatically unlock it after 10 seconds
boolean res = rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS);
// or
boolean res = rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();

8.6. Semaphore

Redis based distributed Semaphore object for Java similar to java.util.concurrent.Semaphore object.

RSemaphore semaphore = redisson.getSemaphore("semaphore");
semaphore.acquire();
//or
semaphore.acquireAsync();
semaphore.acquire(23);
semaphore.tryAcquire();
//or
semaphore.tryAcquireAsync();
semaphore.tryAcquire(23, TimeUnit.SECONDS);
//or
semaphore.tryAcquireAsync(23, TimeUnit.SECONDS);
semaphore.release(10);
semaphore.release();
//or
semaphore.releaseAsync();

8.7. PermitExpirableSemaphore

Redis based distributed Semaphore object for Java with lease time parameter support for each acquired permit. Each permit identified by own id and could be released only using its id.

RPermitExpirableSemaphore semaphore = redisson.getPermitExpirableSemaphore("mySemaphore");
String permitId = semaphore.acquire();
// acquire permit with lease time = 2 seconds
String permitId = semaphore.acquire(2, TimeUnit.SECONDS);
// ...
semaphore.release(permitId);

8.8. CountDownLatch

Redis based distributed CountDownLatch object for Java has structure similar to java.util.concurrent.CountDownLatch object.

RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.trySetCount(1);
latch.await();

// in other thread or other JVM
RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.countDown();
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.