I tested the below piece of code on HotSpot and Android ART, but with different results.
On HotSpot, MyThread
never gets the updated isRunning
, it get isRunning
= true always...
But when I test it on ART, MyThread
can get the updated isRunning
and exit loop normally...
As I know about java happens-before rule, an non-volatile is not visible across multi-thread, just like the behave of the code below on Hotspot.
Does it depends on VM implementation? Or maybe Android ART has their own optimization?
class MyThread extends Thread {
public boolean isRunning = true;
@Override
public void run() {
System.out.println("MyThread running");
while (true) {
if (isRunning == false) break;
}
System.out.println("MyThread exit");
}
}
public class RunThread{
public static void main(String[] args) {
new RunThread().runMain();
}
public void runMain() {
MyThread thread = new MyThread();
try {
thread.start();
Thread.sleep(500);
thread.isRunning = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
an non-volatile is not visible across multi-thread, just like the behave of the code below on Hotspot.
That's not quite right. A non-volatile write, absent any additional synchronization or other happens-before relationship, is not guaranteed to be visible to a read of that same variable in another thread. It's allowed to be visible, though. I've absolutely seen HotSpot make writes visible across threads despite no happens-before relationship. Based on my experience with this, I suspect that if you remove that Thread.sleep
call in your code, HotSpot will also make the write to isRunning
visible to the thread, despite the lack of any happens-before relationship between the write and the read.
You're definitely right that it's VM-specific, and it's possibly/likely even processor architecture–specific, since different architectures may give different amounts of synchronization for "free", or have different amounts of cache that affect whether a memory address is read from a core's cache or fetched from main memory.
In summary, you should never rely on this sort of behavior working any specific way on any specific VM—it's liable to change without warning.