- Hazelcast Tutorial
- Hazelcast - Home
- Hazelcast - Introduction
- Hazelcast - Setup
- Hazelcast - First Application
- Hazelcast - Configuration
- Setting up multi-node instances
- Hazelcast - Data Structures
- Hazelcast - Client
- Hazelcast - Serialization
- Hazelcast Advanced
- Hazelcast - Spring Integration
- Hazelcast - Monitoring
- Map Reduce & Aggregations
- Hazelcast - Collection Listener
- Common Pitfalls & Performance Tips
- Hazelcast Useful Resources
- Hazelcast - Quick Guide
- Hazelcast - Useful Resources
- Hazelcast - Discussion
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 |