Understanding Java Semaphore Basics with simple Example

Semaphore restricts the number of threads that can concurrently access a shared resource. It allocates permits for allowing access to the shared resource.

When we create an instance of a Semaphore, we specify the total number of permits.

In the below, we have created a Semaphore with 5 permits which means only 5 threads can concurrently access the resource.

Semaphore semaphore = new Semaphore(5);

A thread need to acquire a permit to access the resource.

semaphore.acquire();

The number of permits reduces by 1, when a thread acquires a permit.

The number of permits increases by 1, when a thread releases the permit.

semaphore.release();

When the number of permits becomes zero, the thread trying to acquire a permit remains in blocked state until some other thread releases it’s permit.

Realtime example

Let’s take a realtime example in today’s world.

Due to COVID 19, different restrictions have been put around the World. For our use case, we will take an example of a Grocery Store.

So, this Grocery store allows maximum of 5 customers at any point of time inside it. Now, let’s say, we have 10 customers outside the store who want to barge into the store.

The store will initially allow 5 customers out of 10 to get into it, then when one customer comes out , it allows one of the waiting customers to get in.

Here , in this case, the Grocery Store can be considered as the shared resource, customer as a Runnable(which is executed by a thread) and number of permits as 5.

Let’s implement this in Java 🙂

We will use ExecutorService to create a Fixed Thread Pool for our use case.

package com.java.concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class SemaphoreTest {
	
	public static void main(String[] args) throws InterruptedException {
		Semaphore semaphore = new Semaphore(5);		
		ExecutorService executorService = Executors.newFixedThreadPool(50);
	    IntStream.range(1,10).forEach(i->executorService.execute(new Customer(semaphore,i)));
	    executorService.shutdown();
	    executorService.awaitTermination(1, TimeUnit.MILLISECONDS);
	}
	
	
}
class Customer implements Runnable{
	
	private Semaphore semaphore;
	private int customerNumber;
	
	public Customer(Semaphore semaphore, int customerNumber) {
		this.semaphore= semaphore;
		this.customerNumber= customerNumber;
	}
	@Override
	public void run() {
		try {
			// Trying to acquire a permit. If permit is not available , the thread will be blocked here
			semaphore.acquire();
			System.out.println("Customer:"+customerNumber +" is allowed inside the Grocery Store");
			// Release the permit.
			semaphore.release();
			System.out.println("Customer:"+customerNumber +" goes outside the Grocery Store");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
}
Customer:1 is allowed inside the Grocery Store
Customer:4 is allowed inside the Grocery Store
Customer:5 is allowed inside the Grocery Store
Customer:4 goes outside the Grocery Store
Customer:5 goes outside the Grocery Store
Customer:2 is allowed inside the Grocery Store
Customer:1 goes outside the Grocery Store
Customer:3 is allowed inside the Grocery Store
Customer:7 is allowed inside the Grocery Store
Customer:7 goes outside the Grocery Store
Customer:8 is allowed inside the Grocery Store
Customer:2 goes outside the Grocery Store
Customer:6 is allowed inside the Grocery Store
Customer:9 is allowed inside the Grocery Store
Customer:8 goes outside the Grocery Store
Customer:3 goes outside the Grocery Store
Customer:9 goes outside the Grocery Store
Customer:6 goes outside the Grocery Store

Constructors

Understanding Java Semaphore Basics with simple Example

Methods

The methods marked in red are blocking in nature in the sense that the thread is blocked until a permit is acquired whereas the methods marked in green are non blocking, here the thread is not blocked.

Leave a Reply

Your email address will not be published. Required fields are marked *