Semaphore has been introduced in Java 5 to provide access to shared resources in an effective manner. Semaphore controls the number of threads to access shared resources. Semaphore is initialized with the integer count where only that many threads get access to shared resources.
Consider a real time example of Washroom access at a Railway Station that has only 2 washroom. When both the washroom gets filled, people outside need to wait to get them empty. In this case,
Semaphore is initialized with count as 2. Since the entry to washrooms must be allowed in a fair manner, Semaphore is initialized with fair - true. This make sure clients waiting outside must get fair chance i.e. first one in the queue must get first entry as soon as one of the washroom is available.
Semaphore is initialized with count 2. If 1 person enters the first washroom, Semaphore count is reduced to 1 by giving a call to semaphore.acquire(). When second person enters 2nd washroom, Semaphore is reduced to 0 by calling semaphore.acquire().
Now all the clients are waiting for atleast one washroom to become available. As soon as one of the washroom gets free, Semaphore is incremented to 1 by calling semaphore.release(). As soon as count becomes 1, the client waiting first get access to washroom, and so Semaphore count becomes 0 again and all clients wait in the queue. As soon as 2nd goes empty, Semaphore again increase to 1 by calling semaphore.release() and another client gets a chance.
There is a case when both the washrooms goes empty, in that case, Semaphore count is again incremented to 2.
Here is a realtime implementation of above -
SemaphoreClient.java - This is a client file that initializes Semaphore to 2 and initialize 5 clients to access washroom
package com.learning.semaphore; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Semaphore; public class SemaphoreClient { public static void main(String args[]) { Semaphore washRoomSemaphore = new Semaphore(2, true); List<ClientThread> clientThreads = new ArrayList<ClientThread>(); for(int i = 1; i <= 5; i++) { ClientThread clientThread = new ClientThread(); clientThread.setWashRoomSemaphore(washRoomSemaphore); clientThread.setClientNumber(i); clientThreads.add(clientThread); } for(ClientThread clientThread : clientThreads) { Thread thread = new Thread(clientThread); thread.start(); } } }
ClientThread.java - This is a client thread that acquire and releases Semaphore in order to access Washroom
package com.learning.semaphore; import java.util.concurrent.Semaphore; public class ClientThread implements Runnable { public void run() { System.out.println("Client - " + this.clientNumber + " waiting for Washroom access"); try { this.washRoomSemaphore.acquire(); System.out.println("Client - " + this.clientNumber + " got access to Washroom"); Thread.sleep(2000); } catch (InterruptedException e) { } finally { this.washRoomSemaphore.release(); System.out.println("Client - " + this.clientNumber + " released Washroom"); } } private Semaphore washRoomSemaphore; private int clientNumber; public Semaphore getWashRoomSemaphore() { return washRoomSemaphore; } public void setWashRoomSemaphore(Semaphore washRoomSemaphore) { this.washRoomSemaphore = washRoomSemaphore; } public int getClientNumber() { return clientNumber; } public void setClientNumber(int clientNumber) { this.clientNumber = clientNumber; } }
Output -
Client - 1 waiting for Washroom access Client - 1 got access to Washroom Client - 2 waiting for Washroom access Client - 2 got access to Washroom Client - 3 waiting for Washroom access Client - 4 waiting for Washroom access Client - 5 waiting for Washroom access Client - 3 got access to Washroom Client - 4 got access to Washroom Client - 1 released Washroom Client - 2 released Washroom Client - 4 released Washroom Client - 5 got access to Washroom Client - 3 released Washroom Client - 5 released Washroom
Its visible as soon as 2 threads got access to Washroom, Semaphore is reduced to 0 and other clients enter in wait state.
Informative and helpful.
ReplyDelete