So I just learned about the volatile keyword while writing some examples for a section that I am TAing tomorrow. I wrote a quick program to demonstrate that the ++ and -- operations are not atomic.
public class Q3 {
private static int count = 0;
private static class Worker1 implements Runnable{
public void run(){
for(int i = 0; i < 10000; i++)
count++; //Inner class maintains an implicit reference to its parent
}
}
private static class Worker2 implements Runnable{
public void run(){
for(int i = 0; i < 10000; i++)
count--; //Inner class maintains an implicit reference to its parent
}
}
public static void main(String[] args) throws InterruptedException {
while(true){
Thread T1 = new Thread(new Worker1());
Thread T2 = new Thread(new Worker2());
T1.start();
T2.start();
T1.join();
T2.join();
System.out.println(count);
count = 0;
Thread.sleep(500);
}
}
}
As expected the output of this program is generally along the lines of:
-1521
-39
0
0
0
0
0
0
However, when I change:
private static int count = 0;
to
private static volatile int count = 0;
my output changes to:
0
3077
1
-3365
-1
-2
2144
3
0
-1
1
-2
6
1
1
I've read When exactly do you use the volatile keyword in Java? so I feel like I've got a basic understanding of what the keyword does (maintain synchronization across cached copies of a variable in different threads but is not read-update-write safe). I understand that this code is, of course, not thread safe. It is specifically not thread-safe to act as an example to my students. However, I am curious as to why adding the volatile keyword makes the output not as "stable" as when the keyword is not present.