2

I was going through the use cases for volatile and I have encountered the below scenario:

private static boolean stop = false;
public static void main(String[] args) throws InterruptedException {
    Thread runner = new Thread(new Runnable() {

        @Override
        public void run() {
            int i = 0;
            long start = System.currentTimeMillis();
            while(!stop){
                i++;
            }
            System.out.println("I m done after "+(System.currentTimeMillis() - start));
        }
    });

    runner.start();
    Thread.sleep(2000);
    stop = true;
}

The above code runs indefinitely. Which is fine due to hoisting done by the compiler in an attempt to optimize the code. However, if I replace, i++ with some other statement e.g. System.out.println("Hello"). It stops after 2 seconds.

Why the behavior is like this? I am using jdk1.7.0_51.

Note: I know I should declare stop as volatile. However, I would like to know the reason for the behavior in the above case.

Somnath Musib
  • 3,548
  • 3
  • 34
  • 47
  • from a lame point of view, increasing a value is is easier than writing to stream. :). – Elltz May 09 '16 at 11:32
  • One reason I can think of is that i++ is converted into Java Byte Code which doesn't use I/O where as System.out.println is actually I/O. This may give enough time to see the change in boolean variable – shazin May 09 '16 at 11:33

1 Answers1

0

The standard output is a shared resource across threads. Java's PrintStream class is made thread-safe using synchronized blocks, and all synchronized blocks are memory barriers in java, that's why changes on the stop field become visible inside the loop. However, you shouldn't rely on this.

For example, take a look at the PrintStream.println implementation:

public void println(String paramString)
{
  synchronized (this)
  {
    print(paramString);
    newLine();
  }
}
Tamas Hegedus
  • 28,755
  • 12
  • 63
  • 97