A **Semaphore** in Java Concurrency is a utility that controls access to a shared resource using a set of virtual **permits**. Unlike a standard mutual exclusion lock (Mutex) which only allows one thread, a Semaphore can allow multiple threads to access a resource in parallel up to a configured limit.
Imagine an ATM bank vestibule that contains exactly **2 ATM machines** inside. A security guard stands outside holding exactly **2 keys (permits)**:
- Alice arrives first. The guard hands her a key, and she enters the booth (1 permit remaining).
- Bob arrives second. The guard hands him the second key, and he enters (0 permits remaining).
- Charlie arrives third. Since there are no keys left, the guard makes him wait outside in a blocked queue.
- Once Alice finished her transaction and leaves, she **returns the key (releases permit)** to the guard. The guard immediately hands it to Charlie, who can now enter.
Implementing Semaphore in Java
Using semaphore.acquire() locks a thread if no permits are available, and semaphore.release() returns a permit to the pool:
package io.practise.threadsExample;
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
// Only 2 threads can access the resource simultaneously
static Semaphore semaphore = new Semaphore(2);
public static void main(String[] args) {
new MyAtmThread("Alice").start();
new MyAtmThread("Bob").start();
new MyAtmThread("Charlie").start();
}
static class MyAtmThread extends Thread {
public MyAtmThread(String name) {
super(name);
}
@Override
public void run() {
try {
System.out.println(getName() + " is waiting to enter the ATM booth...");
// Acquire a permit
semaphore.acquire();
System.out.println(getName() + " entered the booth and is doing transactions.");
Thread.sleep(2000); // Simulate transaction processing
System.out.println(getName() + " is leaving the ATM booth.");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// Always release permit in finally block to prevent thread deadlocks
semaphore.release();
}
}
}
}
Conclusion
Semaphores are highly useful for rate-limiting calls to external APIs, managing database connection pools, or shielding expensive physical server resources from concurrent overload.