Tuesday, June 25, 2019

Volatile Vs Static In Java

Volatile Vs Static
Now let's understand

Static Variable While using a static variable in Java,that means, there will be only one copy of that variable, no matter how many objects of the class are created. The variable will be accessible even with no Objects created at all. However, threads may have locally cached values of it
.
Volatile Variable While a variable is volatile but not static, there will be one variable for each Object. So there is no difference from a normal variable but totally different from static. However, even with Object fields, a thread may cache a variable value locally.

Instance variable (non-static, non-volatile) if two threads update a variable of the same Object concurrently, and the variable is not declared volatile, there could be a case in which one of the thread has in cache an old value.

Even if you access a static value through multiple threads, each thread can have it’s local cached copy! To avoid this you can declare the variable as static volatile and this will force the thread to read each time the global value.
However, volatile is not a substitute for proper synchronisation! For instance:

public class TestObjectClass {
 
 public int nonStatic = 0;;
 public static int staticVar = 0;
 public volatile int volatileVar = 0;
 public static volatile int staticVolatileVar = 0;
}
First understand how Volatile keyword work in multithreading.

public class VolatileVarExample {

 public static void main(String[] args) {

  ThreadOne t1 = new ThreadOne(new TestObjectClass());
  ThreadTwo t2 = new ThreadTwo(new TestObjectClass());
  t1.start();
  t2.start();
 }
}

class ThreadOne extends Thread {
 private TestObjectClass testObjectClass;

 public ThreadOne(TestObjectClass testObjectClass) {
  this.testObjectClass = testObjectClass;
 }

 public void run() {
  synchronized (testObjectClass) {
   while (testObjectClass.volatileVar < 10) {
    ++testObjectClass.volatileVar;
    System.out
      .println("ThreadOne ##### increase value By ThreadOne:=======>" + testObjectClass.volatileVar);
    try {
     Thread.sleep(400);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
  }
 }
}

class ThreadTwo extends Thread {

 private TestObjectClass testObjectClass;

 public ThreadTwo(TestObjectClass testObjectClass) {
  this.testObjectClass = testObjectClass;
 }

 public void run() {
  synchronized (testObjectClass) {
   while (testObjectClass.volatileVar < 10) {
    ++testObjectClass.volatileVar;
    System.out.println("ThreadTwo ##### increase value By ThreadTwo:==>" + testObjectClass.volatileVar);
    try {
     Thread.sleep(500);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
  }
 }

}

Output of above program using Volatile keword. (Using different object of same class)

ThreadOne ##### increase value By ThreadOne:=======>1
ThreadTwo ##### increase value By ThreadTwo:==>1
ThreadOne ##### increase value By ThreadOne:=======>2
ThreadTwo ##### increase value By ThreadTwo:==>2
ThreadOne ##### increase value By ThreadOne:=======>3
ThreadTwo ##### increase value By ThreadTwo:==>3
ThreadOne ##### increase value By ThreadOne:=======>4
ThreadTwo ##### increase value By ThreadTwo:==>4
ThreadOne ##### increase value By ThreadOne:=======>5
ThreadTwo ##### increase value By ThreadTwo:==>5
ThreadOne ##### increase value By ThreadOne:=======>6
ThreadOne ##### increase value By ThreadOne:=======>7
ThreadTwo ##### increase value By ThreadTwo:==>6
ThreadOne ##### increase value By ThreadOne:=======>8
ThreadTwo ##### increase value By ThreadTwo:==>7
ThreadOne ##### increase value By ThreadOne:=======>9
ThreadTwo ##### increase value By ThreadTwo:==>8
ThreadOne ##### increase value By ThreadOne:=======>10
ThreadTwo ##### increase value By ThreadTwo:==>9
ThreadTwo ##### increase value By ThreadTwo:==>10

you can see in the output of above program. ThreadTwo can not access the value of "VolatileVar" which is increase by ThreadOne. (By using different object of same class) i.e. there will be one variable for each Object same like instance(non-volatile) variable.

Example: Volatile variable with same object (single object) of same class.
public class VolatileVarExample2 {

 public static void main(String[] args) {

  TestObjectClass testObjectClass = new TestObjectClass();
  Thread t1 = new ThreadOne11(testObjectClass);
  Thread t2 = new ThreadTwo22(testObjectClass);
  t1.start();
  t2.start();
 }
}

class ThreadOne11 extends Thread {
 private TestObjectClass testObjectClass;

 public ThreadOne11(TestObjectClass testObjectClass) {
  this.testObjectClass = testObjectClass;
 }

 public void run() {

  System.out.println("Thread name : ThreadOne - Start");
  while (testObjectClass.volatileVar < 10) {
   ++testObjectClass.volatileVar;
   System.out.println("ThreadOne ##### increase value By ThreadOne:==>" + testObjectClass.volatileVar);
   try {
    Thread.sleep(400);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
}

class ThreadTwo22 extends Thread {

 private TestObjectClass testObjectClass;

 public ThreadTwo22(TestObjectClass testObjectClass) {
  this.testObjectClass = testObjectClass;
 }

 public void run() {
  System.out.println("Thread name : ThreadTwo - Start");
  while (testObjectClass.volatileVar < 10) {
   ++testObjectClass.volatileVar;
   System.out.println("ThreadTwo ##### increase value By ThreadTwo:======>" + testObjectClass.volatileVar);
   try {
    Thread.sleep(500);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
}

Output of above program.
Thread name : ThreadOne - Start
Thread name : ThreadTwo - Start
ThreadOne ##### increase value By ThreadOne:==>2
ThreadTwo ##### increase value By ThreadTwo:======>2
ThreadOne ##### increase value By ThreadOne:==>3
ThreadTwo ##### increase value By ThreadTwo:======>4
ThreadOne ##### increase value By ThreadOne:==>5
ThreadTwo ##### increase value By ThreadTwo:======>6
ThreadOne ##### increase value By ThreadOne:==>7
ThreadTwo ##### increase value By ThreadTwo:======>8
ThreadOne ##### increase value By ThreadOne:==>9
ThreadOne ##### increase value By ThreadOne:==>10

It's clear from above output of the program that Volatile variable is usefull only while using same object of a class with all threads.

Now let's see the example of static variable "non-Volatile".

public class StaticVarExample {

 public static void main(String[] args) {

  /*
   * TestObjectClass testObjectClass = new TestObjectClass(); ThreadOneStatic t1s
   * = new ThreadOneStatic(testObjectClass); ThreadTwoStatic t2s = new
   * ThreadTwoStatic(testObjectClass);
   */

  ThreadOneStatic t1s = new ThreadOneStatic(new TestObjectClass());
  ThreadTwoStatic t2s = new ThreadTwoStatic(new TestObjectClass());

  t1s.start();
  t2s.start();
 }
}

class ThreadOneStatic extends Thread {
 private TestObjectClass testObjectClass;

 public ThreadOneStatic(TestObjectClass testObjectClass) {
  this.testObjectClass = testObjectClass;
 }

 public void run() {
  while (TestObjectClass.staticVar < 10) {
   ++TestObjectClass.staticVar;
   System.out.println("ThreadOne: increase by ThreadOne:====>" + TestObjectClass.staticVar);
   try {
    Thread.sleep(400);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }

 }
}

class ThreadTwoStatic extends Thread {

 private TestObjectClass testObjectClass;

 public ThreadTwoStatic(TestObjectClass testObjectClass) {
  this.testObjectClass = testObjectClass;
 }

 public void run() {
  while (TestObjectClass.staticVar < 10) {
   ++TestObjectClass.staticVar;
   System.out.println("ThreadTwo: increase by ThreadTwo:============>" + TestObjectClass.staticVar);
   try {
    Thread.sleep(500);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }

}

Output of program using Static Variable "non-volatile".

ThreadOne: increase by ThreadOne:====>1
ThreadTwo: increase by ThreadTwo:============>2
ThreadOne: increase by ThreadOne:====>3
ThreadTwo: increase by ThreadTwo:============>4
ThreadOne: increase by ThreadOne:====>5
ThreadTwo: increase by ThreadTwo:============>6
ThreadOne: increase by ThreadOne:====>7
ThreadTwo: increase by ThreadTwo:============>8
ThreadOne: increase by ThreadOne:====>9
ThreadTwo: increase by ThreadTwo:============>10

As in the output of above program. you can see by using Static Variable "non-volatile".
thread  "ThreadTwo" increase the value of staticVar and Thread "ThreadOne" can access the of staticVar variable. i.e. static variable will have only one copy of that variable, no matter how many objects of the class are created.

Example:-
Now let's see the example using instance variable (non-static and non-volatile).

public class nonStaticVarExample {

 public static void main(String[] args) {
  TestObjectClass testObjectClass = new TestObjectClass();

  ThreadThree t3 = new ThreadThree(testObjectClass);
  ThreadFour t4 = new ThreadFour(testObjectClass);
  t3.start();
  t4.start();
 }

}

class ThreadThree extends Thread {
 private TestObjectClass testObjectClass;

 public ThreadThree(TestObjectClass testObjectClass) {
  this.testObjectClass = testObjectClass;
 }

 public void run() {
  System.out.println("Thread name : ThreadThree - Start");
  int localVar = testObjectClass.nonStatic;
  while (localVar < 5) {
   if (localVar != testObjectClass.nonStatic) {
    System.out.println("Thread ThreadThree ##### get Changes for localVar "+ localVar+ ",  nonStatic "+ testObjectClass.nonStatic);
    localVar = testObjectClass.nonStatic;
    testObjectClass.nonStatic = testObjectClass.nonStatic++;

   }
  }
  System.out.println(Thread.currentThread().getName() + " nonStatic: "+ testObjectClass.nonStatic);
  System.out.println(Thread.currentThread().getName() + " Thread name : ThreadThree - End");

 }
}

class ThreadFour extends Thread {

 private TestObjectClass testObjectClass;

 public ThreadFour(TestObjectClass testObjectClass) {
  this.testObjectClass = testObjectClass;
 }

 public void run() {
  System.out.println("Thread name : ThreadFour - Start");
  int localVar = testObjectClass.nonStatic;
  while (testObjectClass.nonStatic < 5) {
   testObjectClass.nonStatic = ++localVar;
   System.out.println("Thread name: ThreadFour increase value "+ testObjectClass.nonStatic);
   try {
    Thread.sleep(500);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  System.out.println(Thread.currentThread().getName() + " nonStatic: "+ testObjectClass.nonStatic);
  System.out.println("Thread name : ThreadFour - End");
 }

}
Output of above program.

Thread name : ThreadThree - Start
Thread name : ThreadFour - Start
Thread name: ThreadFour increase value 1
Thread ThreadThree ##### get Changes for localVar 0,  nonStatic 1
Thread name: ThreadFour increase value 2
Thread name: ThreadFour increase value 3
Thread name: ThreadFour increase value 4
Thread name: ThreadFour increase value 5
Thread-1 nonStatic: 5
Thread name : ThreadFour - End
As the output of Static Variable and non-static "instance variable". its give same output.

Example Using static static volatile int staticVolatileVar.

public class StaticVolatileExample {

 public static void main(String[] args) {

  /*
   * TestObjectClass testObjectClass = new TestObjectClass(); Thread t1 = new
   * ThreadOne1(testObjectClass); Thread t2 = new ThreadTwo2(testObjectClass);
   */
  
  Thread t1 = new ThreadOne1(new TestObjectClass());
  Thread t2 = new ThreadTwo2(new TestObjectClass());

  t1.start();
  t2.start();
 }
}

class ThreadOne1 extends Thread {
 private TestObjectClass testObjectClass;

 public ThreadOne1(TestObjectClass testObjectClass) {
  this.testObjectClass = testObjectClass;
 }

 public void run() {

  while (TestObjectClass.staticVolatileVar < 10) {
   ++TestObjectClass.staticVolatileVar;
   System.out.println("ThreadOne ##### increase value By ThreadOne:===>" + TestObjectClass.staticVolatileVar);
   try {
    Thread.sleep(400);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
}

class ThreadTwo2 extends Thread {

 private TestObjectClass testObjectClass;

 public ThreadTwo2(TestObjectClass testObjectClass) {
  this.testObjectClass = testObjectClass;
 }

 public void run() {

  while (TestObjectClass.staticVolatileVar < 10) {
   ++TestObjectClass.staticVolatileVar;
   System.out.println(
     "ThreadTwo ####### increase value By ThreadTwo=======> " + TestObjectClass.staticVolatileVar);
   try {
    Thread.sleep(500);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
}

Output of StaticVolatileExample

ThreadOne ##### increase value By ThreadOne:===>2
ThreadTwo ####### increase value By ThreadTwo=======> 2
ThreadOne ##### increase value By ThreadOne:===>3
ThreadTwo ####### increase value By ThreadTwo=======> 4
ThreadOne ##### increase value By ThreadOne:===>5
ThreadTwo ####### increase value By ThreadTwo=======> 6
ThreadOne ##### increase value By ThreadOne:===>7
ThreadTwo ####### increase value By ThreadTwo=======> 8
ThreadOne ##### increase value By ThreadOne:===>9
ThreadTwo ####### increase value By ThreadTwo=======> 10

static volatile variable will force the thread to read each time the global value. i.e. if either we can use different object of same class in all thread or we can use same object of same class, we can check it will create same out. 

No comments:

Post a Comment