I have a very confused question about java volatile read.
I will show two cases to explain my question.
case1:
class TestVolatile {
public boolean running = true;
public volatile boolean volatileField;
void run() {
while(running) {
}
System.out.println("stopped.");
}
public static void main(String[] args) throws InterruptedException {
TestVolatile t = new TestVolatile ();
Thread t1 = new Thread(t::run, "t1");
t1.start();
TimeUnit.SECONDS.sleep(1);
t.running = false;
t1.join();
}
}
case1 won't stop, This is completely understandable because running is not volatile.
Next I will show the second case.
case2:
class TestVolatile {
public boolean running = true;
public volatile boolean volatileField;
void run() {
while(running) {
// just add a volatile read, the code will stop .
if (volatileField) {
}
}
System.out.println("stopped.");
}
public static void main(String[] args) throws InterruptedException {
TestVolatile t = new TestVolatile ();
Thread t1 = new Thread(t::run, "t1");
t1.start();
TimeUnit.SECONDS.sleep(1);
t.running = false;
t1.join();
}
}
just as case2 shows, after add a volatile read in the while loop, the code will stop.
so, why? running is not a volatile field and the code does not write volatileField. is there some happen-before relation can explain case2? thanks a lot for any help!
From the perspective of JMM, why? From the perspective of native code, why?
I have added ** -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*TestVolatile.run -XX:PrintAssemblyOptions=intel ** to jvm option to see native code of TestVolatile.run. But I don't see any special instruction about the volatile read.
my runtime:
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
macOS catalina 10.15.5
2.6 GHz 6-Core Intel Core i7