Tuesday, 6 August 2019

Multi-threading synchronization in Java using Reentrant Lock

                        In this post, we will see Multi-threading synchronization in Java using Reentrant Lock.

                        In previous post, we have seen Multi-threading Synchronization using synchronized method. Check this link: https://www.comrevo.com/2018/09/multi-threading-synchronization-in-java-with-example-programs.html .

                        In this post, we will see how to achieve synchronization using lock.

How ReentrantLock is different from synchronized method/block? 
                      Reentrant Lock has extra advantages over synchronized method/block. 
                      In synchronized method/block, any thread among the waiting threads will be allowed to execute while if we use ReentrantLock, then the thread with more waiting time will be allowed to execute first.
                      ReentrantLock provides some methods, by using which we can terminate the thread which is waiting for longer time. 

How to use ReentrantLock?
                      Lock is an interface provided by package java.util.concurrent.locks. Its implementation is provided by class ReentrantLock. Lock interface provides method lock() to allow calling thread to enter in critical section while other threads wait. unlock() method frees the locking thread and allow other threads to enter in critical section.

Note: critical section is a section or part of program where common resources (variables) get accessed.

                      Check following program without synchronization:
  
Program (SynchronizationLock.java)

class T1
{
  int p=0;
 
  public void add()
   {
       p=p+1;
   }
}

class T extends Thread
{
  T1 t1=new T1();

  public T(T1 t2)
  {
    this.t1=t2;
  }

  public void run()
  {
    t1.add();   
  }
}

class SynchronizationLock
{
  public static void main(String args[]) throws Exception
  {
  int i;
  T1 t1=new T1();

  T q[]=new T[300];
 
  for(i=0;i<300;i++)
     q[i]=new T(t1);

  for(i=0;i<300;i++)
     q[i].start();
 
  for(i=0;i<300;i++)
     q[i].join(); 

  System.out.println("Value of p:"+t1.p);
  }
}

  

Output: 
parag@parag-Inspiron-N4010:~/Desktop/programs/thread$ javac SynchronizationLock.java
parag@parag-Inspiron-N4010:~/Desktop/programs/thread$ java SynchronizationLock
Value of p:298
parag@parag-Inspiron-N4010:~/Desktop/programs/thread$ java SynchronizationLock
Value of p:297
parag@parag-Inspiron-N4010:~/Desktop/programs/thread$ java SynchronizationLock
Value of p:296
parag@parag-Inspiron-N4010:~/Desktop/programs/thread$ java SynchronizationLock
Value of p:300
parag@parag-Inspiron-N4010:~/Desktop/programs/thread$ java SynchronizationLock
Value of p:298

  
                              Check above program and its output. In this program, we are creating 300 threads. All these 300 threads are trying to increment value of variable p which was initialized to 0 in the beginning.  Now check the output, sometimes we are getting value of p as 298, sometimes 300, sometimes 299, and sometimes 297. The reason behind this is few threads are incrementing the value of p simultaneously. 

                               Here, p=p+1 is a critical section. We need to synchronize threads.

                               Now, let us use Lock interface & ReenttrantLock class. Check following program:
   
Program (SynchronizationLock.java)
import java.util.concurrent.locks.*;

class T1
{
  int p=0;
  Lock queueLock = new ReentrantLock();

  public void add()
   {
       queueLock.lock();
       p=p+1;
       queueLock.unlock();
   }
}

class T extends Thread
{
  T1 t1=new T1();

  public T(T1 t2)
  {
    this.t1=t2;
  }

  public void run()
  {
    t1.add();   
  }
}

class SynchronizationLock
{
  public static void main(String args[]) throws Exception
  {
  int i;
  T1 t1=new T1();

  T q[]=new T[300];
 
  for(i=0;i<300;i++)
     q[i]=new T(t1);

  for(i=0;i<300;i++)
     q[i].start();
 
  for(i=0;i<300;i++)
     q[i].join(); 

  System.out.println("Value of p:"+t1.p);
  }
}


  

Output: 

parag@parag-Inspiron-N4010:~/Desktop/programs/thread$ javac SynchronizationLock.java parag@parag-Inspiron-N4010:~/Desktop/programs/thread$ java SynchronizationLock
Value of p:300
parag@parag-Inspiron-N4010:~/Desktop/programs/thread$ java SynchronizationLock
Value of p:300
parag@parag-Inspiron-N4010:~/Desktop/programs/thread$ java SynchronizationLock
Value of p:300
parag@parag-Inspiron-N4010:~/Desktop/programs/thread$ java SynchronizationLock
Value of p:300
parag@parag-Inspiron-N4010:~/Desktop/programs/thread$ java SynchronizationLock
Value of p:300
    
                       Check above program. p=p+1 was the critical section where common resource (variable) p was used. We have locked that statement for a thread which calls lock() method.
                       Here, each time, we are getting value of p as 300 as only one thread is allowed execute statement p=p+1 while all other threads were waiting.

No comments:

Post a comment