Reputation: 878
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;
}
}
Upvotes: 3
Views: 1129
Reputation: 719259
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.
Upvotes: 4
Reputation: 363
The value of ready may be updated but the other thread may never know about it. There you need volatile variables! A thread assumes that the variable is only used by this and only thread. So, it reads its value from the stack that it created.
private static volatile boolean ready;
What volatile does is that it says to your program to ready from the memory, not from the stack.
Actually what jvm does is it translates:
while(flag){...}
To:
if(flag){
while(true){
}
The stack is created when the thread is created. It collectes the values of the variables in order to use them later.
This is what I have understand, correct me if I am wrong!
Upvotes: 1