Semaphore in java - with real world application and programs



In this thread concurrency tutorial we will learn what is java.util.concurrent.Semaphore in java with program and examples. We will learn about Semaphore constructors, what is permits, Semaphore’s important method like acquire and release in thread concurrency in java. We will learn Application of Semaphore in real world (for solving Producer Consumer problem)

Contents of page :
  • 1) What is java.util.concurrent.Semaphore in java?
  • 1.1) Semaphore has 2 constructors in java >
    • Semaphore(int permits)  
    • Semaphore(int permits, boolean fair)
  • 1.2) Semaphore’s acquire() method has 2 forms :
    • void acquire( ) throws InterruptedException
  • void acquire(int permits) throws InterruptedException
  • 1.3) Semaphore’s release() method has 2 forms :
  • void release( )
  • void release(int permits)
  • 2) Program to demonstrate usage of Semaphore in java >
  • Let’s discuss output in detail, to get better understanding of Semaphore program >
  • 3) Application of Semaphore in real world (for solving Producer Consumer problem) >
  • 4) Program - If permits are 0, then acquire() method can acquire lock only when release() method is called.


  1. What is java.util.concurrent.Semaphore in java?
A semaphore controls access to a shared resource by using permits in java.
  • If permits are greater than zero, then semaphore allow access to shared resource.
  • If permits are zero or less than zero, then semaphore does not allow access to shared resource.
These permits are sort of counters, which allow access to the shared resource. Thus, to access the resource, a thread must be granted a permit from the semaphore.

1.1) Semaphore has 2 constructors in java >
  • Semaphore(int permits)  
permits is the initial number of permits available.
This value can be negative, in which case releases must occur before any acquires will be granted, permits is number of threads that can access shared resource at a time.
If permits is 1, then only one threads that can access shared resource at a time.

  • Semaphore(int permits, boolean fair)
permits is the initial number of permits available.
This value can be negative, in which case releases must occur before any acquires will be granted.
By setting fair to true, we ensure that waiting threads are granted a permit in the order in which they requested access.

1.2) Semaphore’s acquire( ) method has 2 forms  in java:
  • void acquire( ) throws InterruptedException
Acquires a permit if one is available and decrements the number of available permits by 1.
If no permit is available then the current thread waits until one of the following things happen >
>some other thread calls release() method on this semaphore or,
>some other thread interrupts the current thread.

  • void acquire(int permits) throws InterruptedException
Acquires permits number of permits if available and decrements the number of available permits by permits.
If permits number of permits are not available then the current thread becomes dormant until  one of the following things happens -
>some other thread calls release() method on this semaphore and available permits become equal to permits or,
>some other thread interrupts the current thread.


1.3) Semaphore’s release( ) method has 2 forms  in java:
  • void release( )
Releases a permit and increases the number of available permits by 1.
For releasing lock by calling release() method it’s not mandatory that thread must have acquired permit by calling acquire() method.

  • void release(int permits)
Releases permits number of permits and increases the number of available permits by permits.
For releasing lock by calling release(int permits) method it’s not mandatory that thread must have acquired permit by calling acquire()/acquire(int permit) method.


2) Program to demonstrate usage of Semaphore in java >
import java.util.concurrent.Semaphore;
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
public class SemaphoreExample {
   static int SharedValue=0;
  
   public static void main(String[] args) {
          Semaphore semaphore=new Semaphore(1);
          System.out.println("Semaphore with 1 permit has been created");

         
          IncrementThread incrementThread=new IncrementThread(semaphore);
          new Thread(incrementThread,"incrementThread").start();
         
          DecrementThread decrementThread=new DecrementThread(semaphore);
          new Thread(decrementThread,"decrementThread").start();
         
   }
}


class IncrementThread implements Runnable{
   Semaphore semaphore;
  
   public IncrementThread(Semaphore s) {
          semaphore=s;     
   }
  
   public void run(){
          System.out.println(Thread.currentThread().getName()+
                       " is waiting for permit");
          try {
                 semaphore.acquire();
                 System.out.println(Thread.currentThread().getName()+
                              " has got permit");
         
                 for(int i=0;i<5;i++){
                       Thread.sleep(1000);
                       System.out.println(Thread.currentThread().getName()+
                                     " > "+SemaphoreExample.SharedValue++);
                 }
                
          } catch (InterruptedException e) {
                 e.printStackTrace();
          }
         
          System.out.println(Thread.currentThread().getName()+
                       " has released permit");
          semaphore.release();
  
   }
  
}




class DecrementThread implements Runnable{
   Semaphore semaphore;
   public DecrementThread(Semaphore s){
          semaphore=s;
   }
  
   public void run(){
          System.out.println(Thread.currentThread().getName()+
                       " is waiting for permit");
         
          try {
                 semaphore.acquire();
                 System.out.println(Thread.currentThread().getName()+
                              " has got permit");
         
                 for(int i=0;i<5;i++){         
                       Thread.sleep(1000);
                       System.out.println(Thread.currentThread().getName()+
                                     " >"+SemaphoreExample.SharedValue--);
                 }
                
          } catch (InterruptedException e) {
                 e.printStackTrace();
          }
         
         
          System.out.println(Thread.currentThread().getName()+
                       " has released permit");
          semaphore.release();
         
         
   }
  
}
/*OUTPUT
 
Semaphore with 1 permit has been created
incrementThread is waiting for permit
incrementThread has got permit
decrementThread is waiting for permit
incrementThread > 0
incrementThread > 1
incrementThread > 2
incrementThread > 3
incrementThread > 4
incrementThread has released permit
decrementThread has got permit
decrementThread >5
decrementThread >4
decrementThread >3
decrementThread >2
decrementThread >1
decrementThread has released permit
*/


Let’s discuss output in detail, to get better understanding of Semaphore usage in program in java >
Note : I have mentioned output in green text.


Semaphore with 1 permit has been created
Initially, Semaphore with 1 permit is created (permit=1).

incrementThread is waiting for permit
incrementThread has entered run() method of IncrementThread  class and is waiting for permit. (permit=1), as permit is 1 thread could soon get permit to access shared resource i.e. SemaphoreExample.SharedValue

incrementThread has got permit
incrementThread has got permit. (Now, permit=0).

decrementThread is waiting for permit
decrementThread has entered run() method of DecrementThread  class and is waiting for permit (permit=0), as permit is 0 thread got to wait for permit to become 1 to access  shared resource i.e. SemaphoreExample.SharedValue

incrementThread > 0
incrementThread > 1
incrementThread > 2
incrementThread > 3
incrementThread > 4
incrementThread continues to increment SemaphoreExample.SharedValue

incrementThread has released permit
incrementThread has released permit by calling release() method on semaphore. (Now, permit=1).

decrementThread has got permit
decrementThread has got permit. (Now, permit=0).

decrementThread >5
decrementThread >4
decrementThread >3
decrementThread >2
decrementThread >1
incrementThread continues to decrement SemaphoreExample.SharedValue

decrementThread has released permit
decrementThread has released permit by calling release() method on semaphore. (Now, permit=1).


3) Application of Semaphore in real world (for solving Producer Consumer problem in java) >

Semaphore can be used for implementing Producer Consumer pattern in java.


Semaphore on producer is created with permit =1. So, that producer can get the permit to produce.
Semaphore on consumer is created with permit =0. So, that consumer could wait for permit to consume. [because initially producer hasn’t produced any product]

Producer gets permit by calling semaphoreProducer.acquire() and starts producing, after producing it calls semaphoreConsumer.release(). So, that consumer could get the  permit to consume.

semaphoreProducer.acquire();
System.out.println("Produced : "+i);
semaphoreConsumer.release();

Consumer gets permit by calling semaphoreConsumer.acquire() and starts consuming, after consuming it calls semaphoreProducer.release(). So, that producer could get the  permit to produce.

semaphoreConsumer.acquire();
System.out.println("Consumed : "+i);
semaphoreProducer.release();


For more detailed information on how Semaphore can be used for implementing Producer Consumer pattern, please refer my next tutorial.



4) Program - If permits are 0, then acquire() method can acquire lock only when release() method is called in java.

import java.util.concurrent.Semaphore;
public class SemaphoreExample {
   public static void main(String[] args) {
          Semaphore semaphore=new Semaphore(0);
          new Thread(new MyRunnable(semaphore),"Thread-1").start();
         
   }
}
class MyRunnable implements Runnable{
   Semaphore semaphore;
  
   public MyRunnable(Semaphore semaphore) {
          this.semaphore=semaphore;     
   }
  
   public void run(){
          System.out.println(Thread.currentThread().getName()+
                       " is waiting for permit");
          try {
                 semaphore.acquire();
                 System.out.println(Thread.currentThread().getName()+
                              " has got permit");
                
          } catch (InterruptedException e) {
                 e.printStackTrace();
          }
  
   }
  
}
/*OUTPUT
Thread-1 is waiting for permit
*/

In above program, we have initialized Semaphore with 0 permits.
So, acquire() method is waiting for some other thread to call release() method for acquiring lock.
release() method has not been called in above program because it was just for demonstration purpose to give you further in depth explanation of Semaphore.



So, in this thread concurrency tutorial we learned what is java.util.concurrent.Semaphore in java with program and examples. We learned about java.util.concurrent.Semaphore constructors, what is permits, java.util.concurrent.Semaphore’s important method like acquire and release in thread concurrency in java. We also learned Application of Semaphore in real world (for solving Producer Consumer problem)



Having any doubt? or you you liked the tutorial! Please comment in below section.
Please express your love by liking JavaMadeSoEasy.com (JMSE) on facebook, following on google+ or Twitter.



RELATED LINKS>

java.util.concurrent.Semaphore in thread concurrency in java  >

java.util.concurrent.Semaphore in java

Implementation of custom/own Semaphore in java


Semaphore used for implementing Producer Consumer pattern

Custom Semaphore used for implementing Producer Consumer pattern



Phaser in thread concurrency in thread concurrency in java  >

java.util.concurrent.Phaser in java



Exchanger in thread concurrency in thread concurrency in java  >

java.util.concurrent.Exchanger in java



Important Similarity and Differences in thread concurrency in java >

Differences between execute() and submit() method of executor framework

Difference between synchronized and ReentrantLock in java

Similarity and Difference between CyclicBarrier and CountDownLatch in Java



Thread concurrency Interviews in java >

eEdit
Must read for you :