Semaphore in Java
Complete Guide with Custom Implementation
Introduction
In multithreading, a Semaphore is used to control access to a shared resource by multiple threads.
It acts as a counter representing the number of permits available.
A Semaphore is part of the java.util.concurrent package.
It can be used for controlling concurrency in cases where a resource has a limited number of slots.
Key Points:
- Semaphores maintain a set of permits.
- Threads acquire permits before accessing a resource and release them afterward.
- Semaphores can be binary (only 1 permit) or counting (multiple permits).
- Used for controlling access to limited resources such as database connections.
How Semaphore Works
- A thread calls acquire() to get a permit.
- If permits are available, the thread continues; otherwise, it waits.
- After finishing work, the thread calls release() to return the permit.
Syntax:
Semaphore semaphore = new Semaphore(int permits);
Here:
- permits = maximum number of permits available.
Example: Using Semaphore
Let’s create a scenario where three threads access a shared resource with only two permits.
Code:
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2); // 2 permits
Runnable task = () -> {
try {
System.out.println(Thread.currentThread().getName() + " is waiting for a permit.");
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " acquired a permit.");
Thread.sleep(2000); // simulate resource usage
System.out.println(Thread.currentThread().getName() + " releasing permit.");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
for (int i = 0; i < 5; i++) {
new Thread(task).start();
}
}
}
Expected Output:
Thread-0 is waiting for a permit.
Thread-0 acquired a permit.
Thread-1 is waiting for a permit.
Thread-1 acquired a permit.
Thread-2 is waiting for a permit.
Thread-3 is waiting for a permit.
Thread-4 is waiting for a permit.
Thread-0 releasing permit.
Thread-2 acquired a permit.
Thread-1 releasing permit.
Thread-3 acquired a permit.
...
Key Methods in Semaphore
| Method | Description |
|---|---|
| acquire() | Acquires a permit (blocks if none available) |
| release() | Releases a permit |
| availablePermits() | Returns the number of available permits |
| tryAcquire() | Attempts to acquire a permit without blocking |
Advantages of CustomSemaphore
- Helps understand concurrency control and permits logic.
- Useful for learning how to manage resource access manually.
- Simple, flexible for custom needs.
Disadvantages
- More prone to errors compared to Java’s built-in Semaphore.
- No advanced features like fairness and interruption handling.
- Needs careful design to avoid deadlocks.
Real-World Use Case
CustomSemaphore can be useful for:
- Limiting access to resources like database connections or API calls.
- Controlling concurrency in thread pools.
- Traffic shaping in networked applications.
The custom implementation of semaphore use the below link:
Custom implementation of Semaphore
Conclusion
Semaphore is a powerful tool for controlling access to resources.
The custom implementation of Semaphore provides insight into low-level concurrency control, teaching how permits and synchronization work.
For production-grade applications, always use Java’s built-in Semaphore because it handles edge cases, fairness, and interruption effectively.
But building a custom version deepens understanding of concurrency principles.
