I have a simple TestThreadClientMode
class to test a race condition. I tried two attempts:
System.out.println(count);
commented in the second thread, the output was:OS: Windows 8.1
flag done set true
...
and the second thread was alive forever. Because the second thread never sees change of the done
flag which was set true by Main thread.
When I uncommented System.out.println(count);
the output was:
OS: Windows 8.1
0
...
190785
190786
flag done set true
Done! Thread-0 true
And the program stopped after 1 second.
How did System.out.println(count);
make the second thread see the change in done
?
public class TestThreadClientMode {
private static boolean done;
public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
public void run() {
int count = 0;
while (!done) {
count ++;
//System.out.println(count);
}
System.out.println("Done! " + Thread.currentThread().getName() + " " + done);
}
}).start();
System.out.println("OS: " + System.getProperty("os.name"));
Thread.sleep(1000);
done = true;
System.out.println("flag done set true ");
}
}
Multiple threads accessing shared data simultaneously may lead to a timing dependent error known as data race condition. Data races may be hidden in the code without interfering or harming the program execution until the moment when threads are scheduled in a scenario (the condition) that break the program execution.
Thread Interference Error. When multiple threads share the same memory, there is a chance that two or more different threads performing different operations on the same data interleave with each other and create inconsistent data in the memory.
A thread in Java is the direction or path that is taken while a program is being executed. Generally, all the programs have at least one thread, known as the main thread, that is provided by the JVM or Java Virtual Machine at the starting of the program's execution.
This is a brilliant example of memory consistency errors. Simply put, the variable is updated but the first thread does not always see the variable change. This issue can be solved by making done
variable volatile
by declaring it like so:
private static volatile boolean done;
In this case, changes to the variable are visible to all threads and the program always terminates after one second.
Update: It appears that using System.out.println
does indeed solve the memory consistency issue - this is because the print function makes use of an underlying stream, which implements synchronization. Synchronization establishes a happens-before relationship as described in the tutorial I linked, which has the same effect as the volatile variable. (Details from this answer. Also credit to @Chris K for pointing out the side effect of the stream operation.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With