Saturday 13 July 2019

Synchronization in Multithreading

  • Synchronized is the modifiers applicable for methods and blocks but not for classes and variables.
  • If multiple Threads are trying to operate simultaneously on the same java object then there may be a chance of data inconsistency problem.
  • To overcome this problem, we should go for Synchronized keyword.
  • If a method or block declared as Synchronized then at a time only one Thread is allowed to execute to that method or block on the given object. So that data inconsistency problem will be resolved.
  • The main advantage of Synchronized keyword is, we can resolve data inconsistency problems but the main disadvantage of Synchronized keyword is, it increases the waiting time of Threads and creates performance problems.
  • Hence if there is no specific requirement then it is not recommended to use Synchronized keyword.
  • Internally Synchronized concept is implemented by using lock. Every object in java has a unique lock.
  • Whenever we are using Synchronized keyword then only lock concept will come into the picture.
  • If a Thread wants to execute Synchronized method on the given object 1st it has to get lock of that object. Once Thread got the lock then it is allowed to execute any synchronized method on that object. Once method execution completes automatically Thread releases the lock. Acquiring and releasing the lock internally takes care by JVM and programmer not responsible for this activity.
  • While a Thread executing any synchronized method on the given object, the remaining Threads are not allowed execute any synchronized method simultaneously on that object. But remaining Threads are allowed to execute any non-synchronized method simultaneously.
  • Lock concept is implemented based on object but not based on method.
  • Synchronized area can be accessed by only one Thread at a time but in case of non-synchronize area can be accessed by any number of Threads simultaneously.
  • Wherever we are performing update operation (add/remove/delete/replace where state of object changing), we should use inside Synchronized method. Where ever object state won’t be changed (read operation) we should use inside non-synchronized method.

Class ReservationSystem {
              checkAvailability() {
                             // we should use Non-Synchronized area
                             //Just read operation
              }
              bookTicket() {
                             // we should use Synchronized area
                             //Update
              }
}

 Example:


class Display
{
              public synchronized void wish(String name)
              {
                             for(int i=0;i<5;i++)
                             {
                                           System.out.print("good morning:");
                                           try
                                           {
                                                          Thread.sleep(1000);
                                           }
                                           catch (InterruptedException e)
                                           {}
                                           System.out.println(name);
                             }
              }
}
class MyThread extends Thread
{
              Display d;
              String name;
              MyThread(Display d,String name)
              {
                             this.d=d; this.name=name;
              }
              public void run()
              {
                             d.wish(name);
              }
}
class SynchronizedDemo
{
              public static void main(String[] args)
              {
                             Display d1=new Display();
                             MyThread t1=new MyThread(d1,"dhoni");
                             MyThread t2=new MyThread(d1,"yuvaraj");
                             t1.start();
                             t2.start();
              }
}

  • If we are not declaring wish() method as synchronized then both Threads will be executed simultaneously and we will get irregular output. 
Output:
good morning:good morning:yuvaraj
good morning:dhoni
good morning:yuvaraj
good morning:dhoni
good morning:yuvaraj
good morning:dhoni
good morning:yuvaraj
good morning:dhoni
good morning:yuvaraj
dhoni

  • If we declare wish()method as synchronized then the Threads will be executed one by one that is until completing the 1st Thread the 2nd Thread will wait in this case we will get regular output. 
Output:
good morning:dhoni
good morning:dhoni
good morning:dhoni
good morning:dhoni
good morning:dhoni
good morning:yuvaraj
good morning:yuvaraj
good morning:yuvaraj
good morning:yuvaraj
good morning:yuvaraj


Case study
Case-1:
Display d1=new Display();
Display d2=new Display();
MyThread t1=new MyThread(d1,"dhoni");
MyThread t2=new MyThread(d2,"yuvaraj");
t1.start();
t2.start();


Diagram:

  • Even though we declared wish() method as synchronized but we will get irregular output in this case, because both Threads are operating on different objects.
Conclusion:
  • If multiple threads are operating on multiple objects then there is no impact of Syncronization.
  • If multiple threads are operating on same java objects then syncronized concept is required (applicable).
Case-2: Class level lock:-
  • Every class in java has a unique lock which is nothing but class level lock. If a Thread wants to execute a static synchronized method then it required class level lock.
  • Once Thread got class level lock then it is allowed to execute any static synchronized method of that class.
  • Once method execution completes automatically releases the lock.
  • While a Thread executing any static synchronized method the remaining Threads are not allow to execute any static synchronized method of that class simultaneously.
  • But remaining Threads are allowed to execute normal synchronized methods, normal static methods, and normal instance methods simultaneously.
  • Class level lock and object lock both are different and there is no relationship between these two.

Class X {
              static synchronized m1();
              static synchronized m2();
              static m3();
              synchronized m4();
              m5();
}



Case-3: Synchronized Block:-
  • If very few lines of code required Synchronization then it not recommended to declare entire method as Synchronized. We have to enclose those few lines of the code by using Synchronized block.
  • The main advantage of Synchronized block over Synchronized method is, it reduces waiting time of Threads and improves performance of the system.
We can declare Synchronized block as follows

Case: 1:- To get lock of current object
  • If Thread got lock of current object then only it is allowed to execute this block.
Synchronized(this)
{
    //statements
}


Case: 2:- To get lock of particular object b

  • If thread got lock of 'b' object then only it is allowed to execute this area.
Synchronized(b)
{
    //statements
}


Case: 3:- To get Class level Lock
Synchronized(Display.class)
{
    //statements
}

  • If thread got class level lock of Display then only it allowed to execute this area.
Note: As the argument to the synchronized block we can pass either object reference or ".class file" and we can't pass primitive values as argument [because lock concept is dependent only for objects and classes but not for primitives].

                                                   Multithreading Agenda
Thanks..!!

No comments:

Post a Comment