Ambition Follwer Ambition Follwer - 1 year ago 64
Java Question

Unable to get expected output in java threading with static var

Hi I am trying to run below code and getting confused with output :

Its also sometime giving me output as below :
A : 7
C : 8
B : 7

Here how its possible that once static value has been changed to 8 and after that when B thread is going to run and going to print its value 7 ! I mean i is static variable then there is only one copy of it.

public class ThreadStaticTest implements Runnable {

static int i = 5;

public static void main(String[] args) {
ThreadStaticTest obj = new ThreadStaticTest();
Thread t1 = new Thread(obj);
Thread t2 = new Thread(obj);
Thread t3 = new Thread(obj);



public void run() {
System.out.println(Thread.currentThread().getName()+" : "+i);

Answer Source

Think of i++ as three different operations:

  1. fetch i (onto the JVMs stack, the JVM is a stack machine)
  2. increment top of stack
  3. store top of stack back into variable i.

Indeed, OpenJDK 8's javac compiles the run() method into:

public void run();
      0: getstatic     #11                 // Field i:I
      3: iconst_1
      4: iadd
      5: putstatic     #11                 // Field i:I

Additionally, because i is not volatile, the JVM is allowed to optimize read access, that is, it can re-use the earlier value already on the stack for the println() call. So the println() call will typically see the value from the perspective of the current thread, not the stored value. And things can only get "worse" when the byte code is compiled into native code with access to multiple registers.

There is a getstatic invocation before the println() in byte code, but --as noted-- it will probably get optimized away. There's no guarantee what value will be read by it, anyway. You cannot even be sure that the value printed is the value seen by the same thread earlier.

Now, consider the following order of operations, assuming i = 6.

  1. Thread A: fetches i
  2. Thread C: fetches i
  3. Thread A: increments i
  4. Thread A: stores i
  5. Thread B: fetches i
  6. Thread B: increments i
  7. Thread B: stores i
  8. Thread C: increments i
  9. Thread C: stores i

What do we get?

  • A fetches 6, and stores 7, probably prints 7.
  • B fetches 7 and stores 8, probably prints 8.
  • C fetches 6 and stores 7, probably prints 7.

You should get different result for each run, because there's nothing that guarantees this order of execution.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download