Hazelcast - ILock



The java.util.concurrent.locks.Lock provides an interface which can be implemented and used for locking critical sections when working in a multithreaded environment in a JVM.

Similarly, ILock extends the interface to provide a distributed version of Java Lock. It provides similar functions: lock, unlock, tryLock

But a major difference between ILock and Java Lock is that while Java Lock provides protection of critical section from threads in a single JVM, ILock provides synchronization for threads in a single JVM as well as multiple JVMs.

ILock has one synchronous backup meaning that if we have a setup where we have, say, 5 JVMs running, only two JVMs will hold this variable.

Let's look at an example of the useful functions.

Acquiring and Releasing Lock

Let’s say we execute the following code on two JVMs.

Example

public static void main(String... args) throws IOException, InterruptedException {
   //initialize hazelcast instance
   HazelcastInstance hazelcast = Hazelcast.newHazelcastInstance();
   // create a lock
   ILock hzLock = hazelcast.getLock("lock_1");
   IAtomicLong counter = hazelcast.getAtomicLong("counter");
   // acquire lock
   hzLock.lock();
   System.out.println("Acquiring Lock");
   try{
      Thread.sleep(5000);
      System.out.println("Incrementing Counter");
      counter.incrementAndGet();
      System.out.println("Counter: " + counter.get());
   }
   finally {
      // release lock
      System.out.println("Lock Released");
      hzLock.unlock();
   }
   System.exit(0);
}

Output

The output of the above function shows that the second JVM was able to acquire lock only after first JVM released the lock.

Acquired Lock
Incrementing Counter
Counter: 1
Lock Released
Acquired Lock
Incrementing Counter
Counter: 2
Lock Released

Using tryLock instead of Lock

To reduce the chances of deadlock, it is recommended to use tryLock(timeout, unit) method instead lock(). By default, the lock() has a timeout of 5 mins and throws OperationTimeoutException exception if lock is not acquired in that timespan. tryLock instead returns a Boolean based on whether the lock is acquired or not in the provided timespan.

Example

Let’s execute the following code on two JVMs.

public static void main(String... args) throws IOException, InterruptedException {
   //initialize hazelcast instance
   HazelcastInstance hazelcast = Hazelcast.newHazelcastInstance();
   // create a lock
   ILock hzLock = hazelcast.getLock("lock_1");
   // acquire lock
   if(hzLock.tryLock(2000, TimeUnit.SECONDS)) {
      System.out.println("Acquired Lock");
      Thread.sleep(5000);
      System.out.println("Lock Released");
      hzLock.unlock();
   }
   else
      System.out.println("Couldn't acquire lock");
      System.exit(0);
}

Output

The output for the code would be −

Acquired Lock
Couldn't acquire lock
Lock Released

Good practices and know-hows

  • While acquiring locks can be very useful, it is recommended to keep the critical section as short as possible. This ensures that the performance does not degrade and it also reduces the chances of a deadlock.

  • If a member (which has acquired) goes down, the lock is automatically released and is up for grabs for other members.

  • The lock is rentrant; it ensures that the same thread can acquire a lock multiple times without causing a deadlock.

Useful Methods

Sr.No Function Name & Description
1

lock()

Acquire the provided lock instance so that no other thread can acquire it. If unavailable, it waits indefinitely till lock is acquired.

2

unlock()

Release the acquire lock

3

tryLock(long time, TimeUnit unit)

Try to acquire lock in the given time window. Return true if the lock is acquired, else false.

4

isLocked()

Check if the lock is already acquired by some other thread

hazelcast_data_structures.htm
Advertisements