3

I done example program to understand how volatile work. In the below example Even without volatile the program work fine. Could some one help me to understand how the program works fine without volatile?

public class VolatileExp { private /*volatile*/ boolean statusFlag=false; private void changeState() { try { int counter=0; while (!statusFlag) { System.err.println("counter: "+counter++); //Thread.sleep(100); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String args[]) { final VolatileExp hello = new VolatileExp(); Thread t1 = new Thread(new Runnable() { @Override public void run() { hello.changeState(); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(2000); hello.statusFlag=true; System.err.println("setting the status flag "); } catch (Exception e) { e.printStackTrace(); } } }); t1.start(); t2.start(); } } 
4
  • 6
    The program works fine, but it's not guaranteed to work fine. Maybe one in a billion times it will be an infinite loop. This is one reason multithreading is hard. Commented May 28, 2014 at 12:11
  • A few things to try to make that misbehave: Use -server, -client, use a 64-bit and a 32-bit version, add non-default optimizations to the jvm, remove default optimizations, and try a different platform. Commented May 28, 2014 at 12:45
  • Also, your CPU architecture will largely influence this. Volatile adds a write memory barrier after the field access that guarantees that cpu registers are flushed to cache. So, if you are running this in a multicpu (or multicore) architecture you might bump into an issue even faster since unflushed registers fore cpu1 (which could be running thread1) won't be visible to cpu2 (which could be running thread2). But again, how @immibis said, to reproduce it is matter of luck at some point. Commented May 28, 2014 at 13:04
  • @immibis, That's true, but what's maybe more significant is that it might not ever work in somebody else's JVM. Commented May 28, 2014 at 13:08

1 Answer 1

4

There are several reasons why you can’t observe missing updates for your non-volatile variable.

As pointed out by others in the comments, you can’t rely on failures to happen. In this very example, your program runs too short, so the optimizer won’t make any effort here. Running your program with the       -server option will change that.

Further, you are executing a System.err.println(…); statement within the loop which is internally synchronized. Hence, the heap variables will be re-read in every iteration unless the optimizer decides to enlarge the synchronized code block to cover the entire loop (which is rather unlikely as this would imply holding a lock forever). So after the heap value changed, sooner or later, the first thread will eventually read the changed flag.

Since the second thread also invokes System.err.println(…); after changing the flag it will be forced to actually write the updated values to the heap so both threads are implicitly synchronized on System.err. But even without doing the printout the second thread will eventually write the value to the heap as the thread ends afterwards.

So you have a program that works on most systems due to side-effects but is still broken. Note that in theory the first thread running in a loop consuming 100% CPU time could force the second thread to never run and thus never set the termination flag. However, most today’s systems will preemptively switch between threads.

Even if it worked every time, relying on it was very dangerous as it is not easy to see the side-effects on which it relies which means, simple changes like removing the print statement in the first thread and running with the -server option (or on any other JVM performing similar optimizations) would turn the program from accidentally running into likely breaking.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.