Search code examples
javamultithreadingwhile-loopinfinite-loopprintln

Do while loops stop executing after a while?


So Im experimenting a bit with multithreading currently, since im still pretty new to Java. Now, I have multiple threads that all influence the same long variable. However, it seems that afer a while of not doing anything but checking the if statement the while loop just stops executing (as in, it loops infinitely). It does work if i just print something within the while-loop.

Does not work:

while(true){
  if(longVariable < 2)
    break;
}

Does somehow work:

while(true){
  System.out.println("hi");
  if(longVariable < 2)
    break;
}

Why is this?


Solution

  • while(true){
      if(longVariable < 2)
        break;
    }
    

    In this code, there is no reason for the JVM to believe that longVariable will ever change. It can effectively rewrite it to:

    long cached = longVariable;
    while(true){
      if(cached < 2)
        break;
    }
    

    Which loops infinitely if longVariable is at least two when it executes, because nothing can change cached.

    You have to give the compiler a hint that this rewrite isn't allowed. It works with the System.out.println on your JVM because it happens to be implemented with synchronization (which is common, but not required). This inserts memory barriers which means that the cached value of longVariable is invalidated, and has to be read again.

    But it's not guaranteed to work. To make it work correctly, either declare the variable volatile:

    volatile long longVariable
    

    which prevents its value from being cached.

    Or use something like an AtomicLong instead of a plain long variable.

    Or, most onerously, use explicit synchronization (ensuring that all reads of and writes to the variable are synchronized on the same "something"):

    long v;
    synchronized (something) {
      v = longVariable;
    }
    if (v < 2) ...