Implementation of custom/own Semaphore in java - with full program and application



In previous thread concurrency tutorial we will learn what is java.util.concurrent.Semaphore in java. Now in this thread concurrency tutorial we will learn how to implement your own Semaphore in java with program and examples. We will learn how to create own Semaphore constructors, what is permits, how to create custom Semaphore’s important method like acquire and release in thread concurrency in java. We will learn Application of custom/own Semaphore in real world (for solving Producer Consumer problem).


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

1) Custom Semaphore in java >
In previous tutorial we read how to use  Semaphore in java. In this post we will be implementing custom Semaphore. This post intends you give you basic functionality of Semaphore using your own java code


A custom  semaphore controls access to a shared resource by using permits.
  • 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) Custom Semaphore’s constructors in java >
  • SemaphoreCustom (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.


CODE >
  public SemaphoreCustom(int permits) {
         this.permits=permits;
  }

1.2) Custom Semaphore’s acquire() method :
  • 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.


CODE >
  public synchronized void acquire() throws InterruptedException {
          //Acquires a permit, if permits is greater than 0 decrements
          //the number of available permits by 1.
          if(permits > 0){
                 permits--;
          }

          //permit is not available wait, when thread
          //is notified it decrements the permits by 1
          else{
                 this.wait();
                 permits--;
          }
   }

1.3) Custom Semaphore’s release() method :
  • 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.


CODE >
   public synchronized void release() {
          //increases the number of available permits by 1.
          permits++;
         
          //If permits are greater than 0, notify waiting threads.
          if(permits > 0)
                 this.notify();
   }

2) Custom Semaphore’s code in java >
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
/**
* @author AnkitMittal
* Copyright (c), AnkitMittal .
* All Contents are copyrighted and must not be reproduced in any form.
* A semaphore controls access to a shared resource by using permits.
   - 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.
*/
class SemaphoreCustom{
  
   private 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.
   */
   public SemaphoreCustom(int permits) {
          this.permits=permits;
   }
   /**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.
   */
   public synchronized void acquire() throws InterruptedException {
          //Acquires a permit, if permits is greater than 0 decrements
          //the number of available permits by 1.
          if(permits > 0){
                 permits--;
          }
          //permit is not available wait, when thread
          //is notified it decrements the permits by 1
          else{
                 this.wait();
                 permits--;
          }
   }
   /** 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.
   */
   public synchronized void release() {
          //increases the number of available permits by 1.
          permits++;
         
          //If permits are greater than 0, notify waiting threads.
          if(permits > 0)
                 this.notify();
   }
}

3) Program to demonstrate usage of Custom Semaphore in java >
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
/**
* @author AnkitMittal
* Copyright (c), AnkitMittal .
* All Contents are copyrighted and must not be reproduced in any form.
* A semaphore controls access to a shared resource by using permits.
   - 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.
*/
class SemaphoreCustom{
  
   private 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.
   */
   public SemaphoreCustom(int permits) {
          this.permits=permits;
   }
   /**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.
   */
   public synchronized void acquire() throws InterruptedException {
          //Acquires a permit, if permits is greater than 0 decrements
          //the number of available permits by 1.
          if(permits > 0){
                 permits--;
          }
          //permit is not available wait, when thread
          //is notified it decrements the permits by 1
          else{
                 this.wait();
                 permits--;
          }
   }
   /** 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.
   */
   public synchronized void release() {
          //increases the number of available permits by 1.
          permits++;
         
          //If permits are greater than 0, notify waiting threads.
          if(permits > 0)
                 this.notify();
   }
}

/**
* Main class, for testing SemaphoreCustom
*/
public class SemaphoreCustomTest {
   static int SharedValue=0;
  
   public static void main(String[] args) {
          SemaphoreCustom semaphore=new SemaphoreCustom(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{
   SemaphoreCustom semaphoreCustom;
  
   public IncrementThread(SemaphoreCustom semaphoreCustom) {
          this.semaphoreCustom=semaphoreCustom;       
   }
  
   public void run(){
          System.out.println(Thread.currentThread().getName()+
                       " is waiting for permit");
          try {
                 semaphoreCustom.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()+
                                     " > "+SemaphoreCustomTest.SharedValue++);
                 }
                
          } catch (InterruptedException e) {
                 e.printStackTrace();
          }
         
          System.out.println(Thread.currentThread().getName()+
                       " has released permit");
          semaphoreCustom.release();
  
   }
  
}





class DecrementThread implements Runnable{
   SemaphoreCustom semaphoreCustom;
   public DecrementThread(SemaphoreCustom semaphoreCustom){
          this.semaphoreCustom=semaphoreCustom;
   }
  
   public void run(){
          System.out.println(Thread.currentThread().getName()+
                       " is waiting for permit");
         
          try {
                 semaphoreCustom.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()+
                                     " >"+SemaphoreCustomTest.SharedValue--);
                 }
                
          } catch (InterruptedException e) {
                 e.printStackTrace();
          }
         
         
          System.out.println(Thread.currentThread().getName()+
                       " has released permit");
          semaphoreCustom.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 Custom Semaphore usage in program in java >
Note : I have mentioned output in green text.

Semaphore with 1 permit has been created
Initially, custom 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).

4) Application of Custom Semaphore in real world (for solving Producer Consumer problem) >


Custom Semaphore can be used for implementing Producer Consumer pattern.




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 Custom Semaphore can be used for implementing Producer Consumer pattern, please refer my next tutorial.


5) Program - If permits are 0, then acquire() method can acquire lock only when release() method is called >


public class SemaphoreExample {
   public static void main(String[] args) {
          SemaphoreCustom semaphore=new SemaphoreCustom(0);
          new Thread(new MyRunnable(semaphore),"Thread-1").start();
         
   }
}
class MyRunnable implements Runnable{
   SemaphoreCustom semaphore;
  
   public MyRunnable(SemaphoreCustom 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 Custom 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 previous thread concurrency tutorial we learned what is java.util.concurrent.Semaphore in java. And in this thread concurrency tutorial we learned how to implement your own Semaphore in java with program and examples. We also learned how to create own Semaphore constructors, what is permits, how to create custom Semaphore’s important method like acquire and release in thread concurrency in java. We also learned application of custom/own 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>

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


CountDownLatch in thread concurrency in java  >

java.util.concurrent.CountDownLatch in java

Implementation of custom/own CountDownLatch in java


CyclicBarrier in thread concurrency in java  >

java.util.concurrent.CyclicBarrier in java

Implementation of custom/own CyclicBarrier in java



Thread concurrency Interviews >

eEdit
Must read for you :