I was trying examples from JCIP and Below program should not work but even if I execute it say 20 times it always work which means ready
and number
are becoming visible even if it should in this case
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread implements Runnable {
public void run() {
while (!ready)
Thread.yield();
System.out.println(number);
}
}
public static void main(String[] args) {
System.out.println(Runtime.getRuntime().availableProcessors());
//Number of Processor is 4 so 4+1 threads
new Thread(new ReaderThread()).start();
new Thread(new ReaderThread()).start();
new Thread(new ReaderThread()).start();
new Thread(new ReaderThread()).start();
new Thread(new ReaderThread()).start();
number = 42;
ready = true;
}
}
On my machine it always prints
4 -- Number of Processors
42
42
42
42
42
According to Listing 3.1 of JCIP It should sometimes print 0 or should never terminate it also suggest that there is no gaurantee that ready and number written by main thread will be visible to reader thread
Update I added 1000ms sleep in main thread after strating all threads still same output.I know program is broken And I expect it behave that way
What is important to keep in mind is that a broken concurrent program might always work with the right combination of JVM's options, machine architecture etc. That does not make it a good program, as it will probably fail in a different context: the fact that no concurrency issue shows up does not mean there aren't any.
In other words, you can't prove that a concurrent program is correct with testing.
Back to your specific example, I see the same behaviour as what you describe. But, if I remove the
Thread.yield()
instruction in the while loop, 3 out of 8 threads stop and print 42, but the rest don't and the program never ends.This program is broken since
ready
andnumber
should be declared asvolatile
.Due to the fact that
ready
andnumber
are primitive variables, operations on them are atomic but it is not guaranteed that they will be visible by other threads.It seems that the scheduler runs the threads after
main
and that is why they see thenumber
andready
being initialized. But that is just one scheduling.If you add e.g. a
sleep
inmain
so as to affect the scheduler you will see different results.So the book is correct, there is no guarantee whether the
Runnable
s running in separate threads will ever see the variable's being updated since the variables are not declared asvolatile
.Update:
The problem here is that the due to the lack of
volatile
the compiler is free to read the fieldready
just once, and reuse the cached value in each execution of the loop.The program is inherently flawed. And with threading issues the problem usually appears when you deploy your application to the field.... From JSL: