What is the Java equivalent of Mutex?

What is the equivalent of a Mutex in Java, and how can it be implemented?

I’m trying to find out if there’s a Mutex in Java or a way to create one. I initially considered using a Semaphore initialized with 1 permit, but that didn’t seem to work as expected.

For example, consider this code:

try {
   semaphore.acquire();
   // do stuff
   semaphore.release();
} catch (Exception e) {
   semaphore.release();
}

If an exception occurs before acquiring the semaphore, the release call in the catch block will increase the permits, making it no longer behave like a binary semaphore.

Would this be the correct way to handle it?

try {
   semaphore.acquire();
   // do stuff
} catch (Exception e) {
   // handle exception
} finally {
   semaphore.release();
}

Would using a finally block ensure that the semaphore remains binary, or is there a better approach for implementing a mutex in Java?

In my experience, when you need a reliable java mutex, ReentrantLock is the way to go. It offers more control and flexibility than synchronized, making it ideal for complex multi-threaded applications.

import java.util.concurrent.locks.ReentrantLock;

public class MutexExample {
    private final ReentrantLock lock = new ReentrantLock();

    public void criticalSection() {
        lock.lock();
        try {
            System.out.println("Thread " + Thread.currentThread().getName() + " is in the critical section.");
            // Critical section logic here
        } finally {
            lock.unlock();  // Ensures proper unlocking even if an exception occurs
        }
    }
}

:white_check_mark: Why this works well?

  • Ensures proper mutual exclusion.
  • Provides fairness (prevents starvation with fair locking).
  • More flexible than synchronized – supports tryLock() and lockInterruptibly().

Building on @shilpa.chandel’s point, if your use case is straightforward and you want a simpler java mutex approach, you can rely on Java’s built-in synchronized keyword. It automatically handles locking without requiring explicit lock() and unlock() calls.*

public class SynchronizedMutexExample {
    public synchronized void criticalSection() {
        System.out.println("Thread " + Thread.currentThread().getName() + " is in the critical section.");
        // Critical section logic here
    }
}

:white_check_mark: Why use this?

  • Simple and easy to use.
  • No explicit lock management needed.
  • Built directly into Java.

:rotating_light: Downside:

  • Less flexible than ReentrantLock.
  • No tryLock() or lockInterruptibly() support.

Adding to @prynka.chatterjee answer, while synchronized is simple, if you want to extend your java mutex usage across multiple processes or require more control, using Semaphore as a mutex can be a great option.

import java.util.concurrent.Semaphore;

public class SemaphoreMutexExample {
    private final Semaphore semaphore = new Semaphore(1); // Binary semaphore (mutex)

    public void criticalSection() {
        try {
            semaphore.acquire();
            System.out.println("Thread " + Thread.currentThread().getName() + " is in the critical section.");
            // Critical section logic here
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            semaphore.release();
        }
    }
}

:white_check_mark: Why this works?

  • finally block ensures proper release, preventing permit leaks.
  • Suitable for multi-threaded environments.
  • Can be used across multiple processes, unlike synchronized.