0

While testing a usage of a Java volatile keyword I have encountered strange behavior on how a program reads a static variable in a thread, if this variable is being simultaneously modified in other thread.

WriterService is being executed in the first thread, increments the varyingVar 5 times and outputs its value in console.

ReaderService is being executed in the second thread, saves varyingVar value into localVar, checks whether it was changed (comparing with localVar) and outputs varyingVar value if it was changed, otherwise tries infinitely.

 public class Lesson4 {

    private static int varyingVar = 0;

    public void execute() {
        new WriterService().start();
        new ReaderService().start();
    }

    static class WriterService extends Thread {
        @Override
        public void run() {
            while (varyingVar < 5) {
                ++varyingVar;
                System.out.println("Write: " + varyingVar);
            }
        }
    }

    static class ReaderService extends Thread {
        @Override
        public void run() {
            int localVar = varyingVar;
            while (varyingVar < 5) {
                // Magic happens here: if uncomment - code works as expected, not running infinitely
                //System.out.println("checking");
                if (localVar != varyingVar) {
                    System.out.println("Read: " + varyingVar);
                    localVar = varyingVar;
                }
            }
        }
    }
 }

Usage of volatile keyword on varyingVar is 100% clear, when second thread simply caches varyingVar value on the thread start and then infinitely compares it in IF statement, that results in false. This way after WriterService ouptuts all 5 modifications, ReaderService continues to read varyingVar value and sees that it still equals to 0 and hasn't changed (program runs infinitely).

Write: 1
Write: 2
Write: 3
Write: 4
Write: 5
*program is still running*

But here is the thing: if we simply uncomment println block - it solves the problem with varyingVar thread caching as if we've tried to add a volatile keyword. This way program is not running forever and gives me reasons to assume that varying var is no longer cached in the second thread and IF statement in the WHILE block results in true. Here is the output:

checking
*multiple times*
checking
Write: 1
Write: 2
Write: 3
Write: 4
Write: 5
Read: 5

Process finished with exit code 0

The question is how is this even possible, that simple console output can cause reading the variable from the main memory, not the thread one? I assume that there is a hidden third thread created with console output that stimulates JVM to read everything from the main memory, but I haven't found any info that proves it.

TongChen
  • 1,414
  • 1
  • 11
  • 21
Dan Serbyn
  • 105
  • 5

0 Answers0