Java Concurrency
Mutex
Semaphore
Thread Synchronization
Java Multithreading

What is mutex and semaphore in Java ? What is the main difference?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In concurrent programming, synchronization is a crucial aspect that ensures threads access shared resources in a predictable manner. This is necessary to avoid conflicts when multiple threads attempt to access the same resources simultaneously. Java, being a multi-threaded environment, provides various synchronization mechanisms, including mutexes and semaphores. Understanding these constructs is essential for effective thread management and resource allocation.

Mutex in Java

A mutex (short for mutual exclusion) is a programming construct that allows multiple program threads to share the same resource, such as file access, but not simultaneously. When one thread is accessing the resource, a mutex prevents other threads from accessing the same resource. This ensures that data integrity is maintained.

Working of Mutex

In Java, a mutex is generally implemented using locking mechanisms. Starting from Java 5, the java.util.concurrent.locks package provides a ReentrantLock class used extensively as a mutex.

Example of Mutex using ReentrantLock:

java
1import java.util.concurrent.locks.Lock;
2import java.util.concurrent.locks.ReentrantLock;
3
4public class SharedResource {
5    private final Lock lock = new ReentrantLock();
6
7    public void accessResource() {
8        lock.lock(); // Acquiring the lock
9        try {
10            // Critical section accessing the shared resource
11        } finally {
12            lock.unlock(); // Releasing the lock
13        }
14    }
15}

Key Characteristics of Mutex

  • Exclusive access: Ensures only one thread accesses the shared resource at a time.
  • Binary state: A mutex can either be locked or unlocked.
  • Blocking: If a mutex is locked, other threads are blocked until it is released.

Semaphore in Java

A semaphore is a more generalized synchronization construct used to control access by multiple threads to a common resource. It acts like a counter that allows access to a certain number of threads concurrently. Semaphores can be used to manage resource pools, network connections, or database connections.

Working of Semaphore

In Java, the java.util.concurrent package provides the Semaphore class to handle semaphores.

Example of Semaphore:

java
1import java.util.concurrent.Semaphore;
2
3public class ConnectionPool {
4    private final Semaphore semaphore;
5
6    public ConnectionPool(int maxConnections) {
7        semaphore = new Semaphore(maxConnections);
8    }
9
10    public void acquireConnection() throws InterruptedException {
11        semaphore.acquire(); // Acquiring permit
12        try {
13            // Critical section accessing the shared resource
14        } finally {
15            semaphore.release(); // Releasing permit
16        }
17    }
18}

Key Characteristics of Semaphore

  • Multiple threads allowed: Can allow multiple threads to access the critical section.
  • Permits: It maintains a set amount of permits that control access. A thread must acquire a permit to enter and release it afterward.
  • Non-blocking option available: While generally used in a blocking manner, can also be used to poll for a permit.

Key Differences Between Mutex and Semaphore

FeatureMutexSemaphore
Access ControlSingle thread at a timeMultiple threads can access concurrently
RepresentationBinary (locked/unlocked)Integer counter (permits)
Use-CasesExclusive access to resourcesResource pool, connection limits
Blocking BehaviorBlocks other threads entirely until unlockedAllows permissions to be set to manage access levels
ImplementationImplemented using locks (ReentrantLock)Implemented using the Semaphore class

Subtopics

Semaphore vs Counting Semaphore

A counting semaphore is a type of semaphore which has an integer value that denotes the number of tasks that can proceed concurrently. The primary difference compared to a basic semaphore is that it can be used to manage access to multiple instances of a resource.

Fairness in Thread Scheduling

In Java's ReentrantLock and Semaphore, fairness policies can be defined to ensure threads are accessed in a first-come-first-serve manner, minimizing the risk of starvation.

  • Fairness in Mutex: Can be enabled by setting ReentrantLock to true.
  • Fairness in Semaphore: Can also be enabled by initializing Semaphore with fairness policy.

Example:

java
Lock fairLock = new ReentrantLock(true);
Semaphore fairSemaphore = new Semaphore(10, true);

Conclusion

Mutexes and semaphores are vital thread synchronization constructs in Java, each serving different purposes. While mutexes ensure exclusive access to shared resources, semaphores provide a controlling mechanism for how many threads can access particular resources simultaneously. Understanding these concepts is fundamental for designing robust multi-threaded applications in Java.


Course illustration
Course illustration

All Rights Reserved.