I'm currently trying to attempting to study concurrency, specifically "volatile" keyword.
By declaring the counter variable volatile all writes to the counter variable will be written back to main memory immediately. Also, all reads of the counter variable will be read directly from main memory. Here is how the volatile declaration of the counter variable looks
and
When a thread writes to a volatile variable, then not just the volatile variable itself is written to main memory. Also all other variables changed by the thread before writing to the volatile variable are also flushed to main memory. When a thread reads a volatile variable it will also read all other variables from main memory which were flushed to main memory together with the volatile variable.
Source : tutorials.jenkov.com | Java Concurrency - Java Volatile Keyword
Which makes me conclude/assume that any change that i make to a volatile variable will always be visible to all thread. So, I make a code to test it.
TestClass
package org.personal.test1;
class TestClass {
public static int w = 0;
public static int x = 0;
public static int y = 0;
public static volatile int z = 0;
private static final int ITERATIONS = 100000;
public static void sooPlus(int indents) {
for (int i = 0; i < TestClass.ITERATIONS; i++) {
TestClass.w++;
TestClass.x++;
TestClass.y++;
TestClass.z++;
}
}
public static void sooMinus(int indents) {
for (int i = 0; i < TestClass.ITERATIONS; i++) {
TestClass.w--;
TestClass.x--;
TestClass.y--;
TestClass.z--;
}
}
public static synchronized String getVariableValues () {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("(");
stringBuilder.append("w : "+TestClass.w+", ");
stringBuilder.append("x : "+TestClass.x+", ");
stringBuilder.append("y : "+TestClass.y+", ");
stringBuilder.append("z : "+TestClass.z+")");
return stringBuilder.toString();
}
}
Main Class
package org.personal.test1;
/**
* <ol type="I">
* <li>
* <a href="http://tutorials.jenkov.com/java-concurrency/volatile.html">jenkov.com - Java Volatile Keyword</a>
* </li>
* </ol>
*/
public class Main {
public static void main(String[] args) {
Main.call1();
}
private static void call1() {
Main.test1();
}
private static void test1() {
Thread thread1 = new Thread("Thread1") {
@Override
public void run() {
TestClass.sooPlus(1);
}
};
Thread thread2 = new Thread("Thread2") {
@Override
public void run() {
TestClass.sooMinus(4);
}
};
thread1.start();
thread2.start();
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(TestClass.getVariableValues());
}
}
The results that i get were not what i was expecting.
What i get (varies)
(w : -2314, x : -1692, y : -1416, z : -1656)
What I'm expecting
(w : 0, x : 0, y : 0, z : 0)
or at least
(w : -2314, x : -1692, y : -1416, z : 0)
The Questions
- What did I assume/conclude wrong that resulted in a different output than expected?
- Was my testing methodology incorrect? If yes, then how can i fix it?
- (optional) Are there any good tutorial on Java Concurrency that you recommend?
Notes
- I did attempt to read similar questions but i wasn't able to fully understand what the questioner was attempting to do in order to understand his problem.