Pages

Wednesday 29 January 2014

Use of Volatile variable w.r.t. to Synchronization

I'm going to talk about what volatile means in Java. First, you have to understand the Java memory model. And what would be the best way then reading the JLS itself. See here: http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4

Take away from the Java memory Model is that the Java programming language allow compilers and microprocessors to perform optimizations on your code i.e.
  1. Can reorder your statements/instructions. A Just-In-Time compiler in a Java Virtual Machine implementation may rearrange code, or the processor.
  2. Perform Forward Substitution to optimize your code.
One of important statement from the JLS: To determine if the actions of thread t in an execution are legal, we simply evaluate the implementation of thread t as it would be performed in a single-threaded context, as defined in the rest of this specification. 


Consider an example:

class VolThread implements Runnable {
 private boolean stop = false;

 public void stop() {
  stop = true;
 }

 @Override
 public void run() {
  while (!stop) {
   try {
    Thread.sleep(100);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("Running");
  }
 }
}

public class VolTest {
 public static void main(String[] args) {
  VolThread vt = new VolThread();
  Thread t1 = new Thread(vt);
  Thread t2 = new Thread(vt);
  t1.start();
  t2.start();
  vt.stop();
 }
}

In the normal scenario both the threads would get complete as soon as vt.stop has been called. However it is perfectly valid to say that JMM can optimize your code and just replace the while condition block with an infinite block. As JMM can see that your are reading the value of stop variable to decide whether to continue the while block and the value of that variable is not going to change in that Thread t so it can optimize your code and just replace it with the infinite loop. That is an Issue!! And your code is not properly syncronized.

What do you mean by incorrectly synchronized?


When we talk about incorrectly synchronized code in the context of the Java Memory Model, we mean any code where
  1. There is a write of a variable by one thread,
  2. There is a read of the same variable by another thread and
  3. The write and read are not ordered by synchronization
When these rules are violated, we say we have a data race on that variable. A program with a data race is an incorrectly synchronized program.
 
Java allows threads to access shared variables and to ensure that shared variables are consistently and reliably updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that enforces mutual exclusion for those shared variables.

So the above scenario can be handled by:
  1. Using locks
  2. Declaring the stop variable as Volatile
What does Volatile variable do?
  • Reads and writes to the volatile variable go directly to memory i.e. it is not cached.
  • Reads and write of volatile variable cannot be reordered.
  • Writing to a volatile field has the same memory effect as a monitor release, and reading from a volatile field has the same memory effect as a monitor acquire.
  • Java Memory Model ensures that all threads see a consistent value for the variable.
  • A write to a volatile field happens-before every subsequent read of that same volatile field.
Corrected code with volatile variable:

class VolThread implements Runnable {
 private volatile boolean stop = false;

 public void stop() {
  stop = true;
 }

 @Override
 public void run() {
  while (!stop) {
   try {
    Thread.sleep(100);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("Running");
  }
 }
}

public class VolTest {
 public static void main(String[] args) {
  VolThread vt = new VolThread();
  Thread t1 = new Thread(vt);
  Thread t2 = new Thread(vt);
  t1.start();
  t2.start();
  vt.stop();
 }
}
 
You can use volatile variables instead of locks only under a restricted set of circumstances. Both of the following criteria must be met for volatile variables to provide the desired thread-safety:
  1. Writes to the variable do not depend on its current value.
  2. The variable does not participate in invariants with other variables.

 Let me know if this makes sense.

No comments:

Post a Comment