I've encountered this code in a book. It states NoVisibility could loop forever because the value of ready might never become visible to the reader thread.
I'm confused by this statement. In order for the loop to run forever, ready
must always be false, which is the default value. This means it must fail at executing ready = true;
because the reader thread will always read the ready
variable from memory. the assignment happens in CPU and it must have some problem in flushing the data back to Main Memory. I think I need some explanation on a situation how it can fail, or I may have missed some other part.
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread {
public void run() {
while (!ready)
Thread.yield();
System.out.println(number);
}
}
public static void main(String[] args) {
new ReaderThread().start();
number = 42;
ready = true;
}
}
In short, the book is correct.
You are assuming that Java will behave intuitively here. In fact, it may not. And, indeed, the Java Language specification allows non-intuitive behavior if you don't follow the rules.
To be more specific, in your example it is not GUARANTEED that the second thread will see the results of the first thread's assignment to ready
1. This is due to such things as:
ready
in a register in the first or second thread.If you want a guarantee that the second thread will see the result of the write then either reads and writes of ready
by the two threads must be (properly) synchronized, or the ready
variable must be declared to be volatile.
So ...
This means it must fail at executing
ready = true;
because the reader thread will always read the ready variable from memory.
... is incorrect. The "because" is not guaranteed by the Java language specification in this example.
Yes. It is non-intuitive. Using your intuition based on an understanding of single-threaded programs is not reliable. If you want to fully understand what is and is not guaranteed, you need to study the specification of the "Java Memory Model" in Section 17.4 of the JLS. Warning: it is NOT an easy read.
1 - It might see the results immediately, or after a short or long delay. Or it might never see them. And the behavior is liable to vary from one system to the next, and with versions of the Java platform. So your program that (by luck) works all of the time on one system may not always work on another system.