2

I'm trying to better understand how does the JIT compiler work for java in respect to volatile variable value caching. Consider the example presented in this question: Infinite loop problem with while loop and threading:

boolean loaded = false; // not volatile!!!
private boolean loadAsset() {
    new Thread(new Runnable() {

        @Override
        public void run() {

            // Do something
            loaded = true;

        }
    }).start();

    while (!loaded) {
        System.out.println("Not Loaded");
    }
    System.out.println("Loaded");
    return false;
}

Since the variable loaded is not declared volatile, the JIT compiler is allowed to "cache" the variable in the registry. It is said that this could in theory result in an infinite loop because the thread that executes the loop might not see that the variable was updated from another thread at some point of time.

But what exactly does "allowed" to cache mean? Is it possible for the variable to get cached sometimes, meaning that if I run this same piece of code in the same JVM (without shutting the JVM down) a million times, the JIT compiler might at some point decide to cache the variable and produce an infinite loop? Or is the JIT compiler consistent, meaning that it will either decide to cache the variable or not and that decision would stand off for all million executions of this piece of code through out the life cycle of the JVM?

Community
  • 1
  • 1
mdzh
  • 1,030
  • 2
  • 17
  • 34
  • 2
    As far as I know (at least in plain Java), neither you nor the JVM control the cache directly. The cache is controlled by the Hardware (CPU). Depending on some factors, variables in cache get overwritten, invalidated, updated, etc... Therefore is is possible that a variable gets cached only sometimes. But by using `volatile`, you instruct the JVM (and therefore the CPU) to never use a cached value and instead use the memory value instead. I do not know whether `volatile` deactivates caching or only instructs to read the value from memory every time. – Turing85 May 20 '16 at 13:53
  • @Turing85: your comment is simply wrong; the questioner got it right. The HotSpot optimizer may emit native code that will hold values in CPU registers instead of re-reading them from the heap. This has the same effect as a cache, in fact, on x86 that’s the main cause for memory visibility issues as the real CPU cache is coherent on this platform. – Holger May 24 '16 at 10:07

2 Answers2

3

Caching here happens on the hardware level where the CPU might decide to read the value of the variable from its cache discarding what other threads have written on their own caches.

The JIT however, might optimise the loop and turn it into and infinite loop because the boolean flag is not set inside the loop, which is not necessary the same as reading a stale value from the cache.

"Allowed to cache" here might be interpreted as, the JIT is not obliged to issue a fence instruction upon reading the variable.

Sleiman Jneidi
  • 22,907
  • 14
  • 56
  • 77
  • That almost answers my question. What I still don't understand is, is it possible that the JIT decides to "optimize" the loop at some point of time? Meaning, is it possible for a program to run in a while and after several mins/hours the JIT will cache a value? – mdzh May 20 '16 at 14:01
  • @mdzh please read my comment. The compiler does not cache anything. The decision on what gets cached and what not is made by the Hardware. – Turing85 May 20 '16 at 14:05
  • @mdzh the problem is that cache is a limited resource, evicting or keeping in cache in controlled by the CPU, JIT however can ask the CPU to invalidate and get a new value every time. So it could be that at some point the value is evicted and a fresh copy is read. – Sleiman Jneidi May 20 '16 at 14:06
  • @mdzh: yes, the JIT may optimize the loop at an arbitrary point of time, outside your control. That decision is influenced by a lot of things. Most notable, it didn’t happen so often in older JVMs as it happens in recent JVMs. – Holger May 24 '16 at 10:19
2

To answer your last question, yes it is possible that the JIT decides to optimize the loop in this way after the program has run a while.

The JVM employs heuristics to decide when to compile or recompile a method at different optimization levels; the optimization in question may only happen at a particular optimization level. A degree of variability is always present with a JIT compiler.

Holger
  • 285,553
  • 42
  • 434
  • 765
vijaysun
  • 46
  • 2