Clustered Locks with Embedded Infinispan
What You Will Learn
How to use Infinispan clustered locks to synchronize concurrent operations across a cluster of embedded nodes using the asynchronous ClusteredLock API.
Prerequisites
-
Java 17+
Step 1: Add Dependencies
Add the Infinispan core and clustered lock modules to your pom.xml:
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-clustered-lock</artifactId>
</dependency>
Step 2: Create a Clustered Lock Manager
Start a clustered cache manager and obtain a ClusteredLockManager from it:
// Setup up a clustered cache manager
GlobalConfigurationBuilder global = GlobalConfigurationBuilder.defaultClusteredBuilder();
// Initialize 1 cache managers
cacheManager = new DefaultCacheManager(global.build());
// Initialize the clustered lock manager from the cache manager
clusteredLockManager = EmbeddedClusteredLockManagerFactory.from(cacheManager);
Step 3: Define and Use a Clustered Lock
Define a named lock and acquire it asynchronously. The lock is non-reentrant by default:
// Define a lock. By default, this lock is non reentrant
clusteredLockManager.defineLock("lock");
// Get a lock interface from each node
lock = clusteredLockManager.get("lock");
Multiple concurrent tryLock calls can be coordinated with CompletableFuture.allOf to wait for all operations to complete:
// Acquire and release the lock 3 times
CompletableFuture<Boolean> call1 = lock.tryLock(1, TimeUnit.SECONDS).whenComplete((r, ex) -> {
if (r) {
System.out.println("lock is acquired by the call 1");
lock.unlock().whenComplete((nil, ex2) -> {
System.out.println("lock is released by the call 1");
counter.incrementAndGet();
});
}
});
CompletableFuture<Boolean> call2 = lock.tryLock(1, TimeUnit.SECONDS).whenComplete((r, ex) -> {
if (r) {
System.out.println("lock is acquired by the call 2");
lock.unlock().whenComplete((nil, ex2) -> {
System.out.println("lock is released by the call 2");
counter.incrementAndGet();
});
}
});
CompletableFuture<Boolean> call3 = lock.tryLock(1, TimeUnit.SECONDS).whenComplete((r, ex) -> {
if (r) {
System.out.println("lock is acquired by the call 3");
lock.unlock().whenComplete((nil, ex2) -> {
System.out.println("lock is released by the call 3");
counter.incrementAndGet();
});
}
});
CompletableFuture.allOf(call1, call2, call3).whenComplete((r, ex) -> {
// Print the value of the counter
System.out.println("Value of the counter is " + counter.get());
}).get(10, TimeUnit.SECONDS);
Step 4: Run the Tutorial
mvn package exec:java
The output shows each lock acquisition and release in sequence, with a final counter value reflecting the number of successful lock operations.
What’s Next
-
Try distributed caching across cluster nodes
-
Use transactions for multi-key atomic operations


