Inspired by this question, I wrote the test:
public class Main {
private static final long TEST_NUMBERS = 5L;
private static final long ITERATION_NUMBER = 100000L;
private static long value;
public static void main(final String [] args) throws Throwable {
for(int i=0; i<TEST_NUMBERS; i++) {
value = 0;
final Thread incrementor = new Thread(new Incrementor());
final Thread checker = new Thread(new Checker());
incrementer.start();
checker.start();
checker.join();
incrementer.join();
}
}
static class Incrementor implements Runnable {
public void run() {
for(int i=0; i<ITERATION_NUMBER; i++){
++value;
}
}
}
static class Checker implements Runnable {
public void run() {
long nonEqualsCount = 0;
for(int i=0; i<ITERATION_NUMBER; i++){
if(value != value) {
++nonEqualsCount;
}
}
System.out.println("nonEqualsCount = " + nonEqualsCount);
}
}
}
This program are printed in common case:
nonEqualsCount = 12; //or other non 0 value;
nonEqualsCount = 0;
nonEqualsCount = 0;
nonEqualsCount = 0;
nonEqualsCount = 0;
First: I explain this behaviour is presence of the JIT-compiler. JIT-compiler cache value non volatile
field for each thread after "warmup". It right?
Second: If first right or not right, how can I verify this?
P.S. - I know about PrintAssebly-option.
Update: enviroment: Windows 7 64bit, JDK 1.7.0_40-b43(Hot Spot).
Incrementing long
variable is not atomic ( is 64-bit large).
In condition (value != value)
: It can happen that between reading value of value
, first thread can change value.
volatile
type is connected with visibility
. Non-volatile variables values can be stale. So your first conclusion seems to be correct.
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