0

Suppose that I have the following classes

Looper.java

class Looper {
  boolean stop;

  void loop() {
    while(!stop) {
      // do something
    }
  }

  void stop() {
    stop = true;
  }
}

Launcher.java

class Launcher {
  public static void main(String[] args) {
    Looper looper = new Looper();
    new Thread(() -> looper.loop()).start();
    new Thread(() -> looper.stop()).start();
  }
}

Is it legal for the compiler/JIT/CPU to transform this Looper class into the following manner such that the loop never ends?

class Looper {
  boolean stop;

  void loop() {
    while(true) { // as stop is always false from the the thread that enters this method
      // do something
    }
  }

  void stop() {
    stop = true;
  }
}
Ashok Koyi
  • 5,327
  • 8
  • 41
  • 50
  • 3
    Yes it is. As long as the field `stop` is not marked as volatile the thread is not required to read it on every pass of the while loop. That means that the thread can read it once and then loop forever. See https://stackoverflow.com/a/25425131/5646962 – Thomas Kläger Oct 15 '18 at 16:59
  • Do u mean that the read of stop variable has to happen everytime a thread enters `loop()` method (may be stop can be replaced by a temp variable)? – Ashok Koyi Oct 15 '18 at 17:23
  • Which means behaviour wise, optimization will work in theory like the example I mentioned, but in practice the stop variable has to be assigned to a temp variable to reduce heap access to keep behaviour the same, is that correct? – Ashok Koyi Oct 15 '18 at 17:25
  • Even using a field will not prevent the boolean being inlined. You need to make it volatile. – Peter Lawrey Oct 15 '18 at 17:30
  • 1
    With your sample code the JVM is allowed to read the `stop` field only once and then execute `while (true) { ... }` or `while (false) { ... }`, as you have no guarantee that the first thread really starts first. It can happen that `looper.stop();` is executed before `looper.loop();` – Thomas Kläger Oct 15 '18 at 17:31
  • I agree about the happens before relationship, but the question is about whether the compiler/JIT/CPU is access `stop` variable under all circumstances as soon a thread enters it (or) it can replace with a simple true blindly, never actually accessing the `stop` variable – Ashok Koyi Oct 15 '18 at 17:32
  • Sure, so whoever optimizes must fetch `stop` atleast once when they enter `loop` method & the optimisation I mentioned is illegal (tho it can effectively behave the same way if `loop()` is entered into first) . Is that correct? – Ashok Koyi Oct 15 '18 at 17:34
  • 1
    Yes, it has to fetch `stop` once - not more (since it is not volatile), but it may also not blindly assume it's state at the start of the `loop()` method. – Thomas Kläger Oct 15 '18 at 17:41
  • Also, is it correct to say that this optimization of accessing just once is disallowed if the `stop` value is changed within the `loop` itself (unless compiler/JIT detects that this code never reaches/the value never changes)? – Ashok Koyi Oct 15 '18 at 17:49

0 Answers0