Semaphore in Java

Semaphore :

Semaphore in Java is used to control the access of shared resource using the counters.Counter is used for counting the available permits that allow access to the shared resource. Therefore, for accessing the resource the thread must be given a permit from the semaphore.

Java 5 comes with a built-in Semaphore , which is available in java.util.concurrent package.  Java java.util.concurrent.Semaphore is called as a Counting Semaphore.

public class Semaphore extends

Object implements

Serializable

Semaphore is a Java concurrency concept , which can be used for :

  • Thread signalling : Thread signalling allows threads to send/receive signal to/from each other. This process can be used for multiple purposes e.g. If thread-1 has to wait for completion of thread-2 to start its execution, it can be achieved by thread signalling.
  • Preventing Race Conditions: Critical section,  in context of Java concurrency , is the section of code which can be accessed by multiple threads at same time but the sequence of threads have a impact on the result of the code. When the above mentioned condition arises in the critical section it is called as Race condition.

To understand the Counting Semaphore , Consider a scenario:

Where multiple threads are sending request to a server and receiving response. But to maintain performance, we need to restrict the number of simultaneous requests to 3 only . We can achieve this by using Semaphore.

Semaphore is initialized with given number of permits. For above mentioned scenario, ,the permits are 3.

Semaphore semaphore = new Semaphore(3);

Below two methods are main and important for Semaphore :

acquire() :

public void acquire() throws InterruptedException

The thread takes the permit by calling acquire method of the Semaphore class. The permit is only provided if  Semaphore has available permits. Otherwise, the calling thread will be blocked until the permit is not released by any thread.

release() :

public void release()

When thread completes its task and the permit is not required by the thread then it calls the release method of the Semaphore to return the availed permit. As soon as , thread calls the release method, permit is revoked from the calling thread and it gets provided to the waiting threads, if any.

semaphore

Simple Illustrative example of SemaPhore : 

import java.util.concurrent.*;

class Test
{
static int cnt = 0;
}

class TestThread extends Thread
{
Semaphore sema;
String threadName;
public TestThread(Semaphore sema, String threadName)
{
super(threadName);
this.sema = sema;
this.threadName = threadName;
}

@Override
public void run() {

// run by thread A

if(this.getName().equals("A"))
{
System.out.println("Starting " + threadName);
try
{
// First, get a permit.
System.out.println(threadName + " is waiting for a permit.");

// acquiring the lock

sema.acquire();

System.out.println(threadName + " gets a permit.");

// Now, accessing the shared resource.
// other waiting threads will wait, until this
// thread release the lock

for(int i=0; i < 5; i++)
{
Test.cnt++;
System.out.println(threadName + ": " + Test.cnt);

// Now, allowing a context switch -- if possible.
// for thread B to execute
Thread.sleep(10);
}
}

catch (InterruptedException exception) {
System.out.println(exception);
}

// Release the permit.
System.out.println(threadName + " releases the permit.");
sema.release();
}

// run by thread B

else
{
System.out.println("Starting " + threadName);
try
{
// First, get a permit.
System.out.println(threadName + " is waiting for a permit.");

// acquiring the lock

sema.acquire();

System.out.println(threadName + " gets a permit.");

// Now, accessing the shared resource.
// other waiting threads will wait, until this
// thread release the lock

for(int i=0; i < 5; i++)
{
Test.cnt--;
System.out.println(threadName + ": " + Test.cnt);

// Now, allowing a context switch -- if possible.
// for thread A to execute
Thread.sleep(10);
}
}

catch (InterruptedException exception) {
System.out.println(exception);
}
// Release the permit.
System.out.println(threadName + " releases the permit.");
sema.release();
}
}
}
// Driver class 
public class SemaphoreDemo 
{ 
public static void main(String args[]) throws InterruptedException 
{ 
// creating a Semaphore object 
// with number of permits 1 
Semaphore sem = new Semaphore(1); 

// creating two threads with name A and B 
// Note that thread A will increment the count 
// and thread B will decrement the count 
TestThread tt1 = new TestThread(sem, "A"); 
TestThread tt2 = new TestThread(sem, "B"); 

// stating threads A and B 
tt1.start(); 
tt2.start(); 

// waiting for threads A and B 
tt1.join(); 
tt2.join(); 

// count will always remain 0 after 
// both threads will complete their execution 
System.out.println("count: " + Test.cnt); 
} 
}

Semaphore and CountDownLatch are being used quite often for granting access to a thread, But there is a difference between Semaphore and CountDownLatch.

Output:

Starting A
A is waiting for a permit.
A gets a permit.
A: 1
Starting B
B is waiting for a permit.
A: 2
A: 3
A: 4
A: 5
A releases the permit.
B gets a permit.
B: 4
B: 3
B: 2
B: 1
B: 0
B releases the permit.
count: 0

Semaphore and CountDownLatch in java is used for same purpose but there is a difference between these two.

Thanks for reading this article. I hope , you like it,

For any suggestions / feedback / question / clarification, Kindly post your comments in the below comment box.

Please subscribe our news letter and connect with social media accounts and don’t miss any articles.

Happy Reading!!!

Newsletter Updates

Enter your name and email address below to subscribe to our newsletter

Leave a Reply