Reputation: 31
Using volatile on a variable reduces the risk of memory consistency error (Please correct me if this reveals some holes in my understanding of any relevant concept). So in the following example even though the variable c1 is volatile, still the occurrence of memory constancy error results in c1 becoming 15 or sometimes 14 in the output rather then the correct output 16.
class Lunch implements Runnable {
private volatile long c1 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
// synchronized(lock1) { c1 is volatile
c1++;
// }
}
public void run() {
try {
inc1();
Thread.sleep(1000);
inc1();
Thread.sleep(1000);
inc1();
Thread.sleep(1000);
inc1();
inc1();
Thread.sleep(1000);
inc1();
Thread.sleep(1000);
inc1();
Thread.sleep(1000);
inc1();
}
catch(InterruptedException e) {
return;
}
}
public long value() {
return c1;
}
public static void main(String args[]) throws InterruptedException {
Lunch l = new Lunch();
Thread t1 = new Thread(l);
Thread t2 = new Thread(l);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(l.value());
}
}
Upvotes: 3
Views: 1188
Reputation: 116256
Atomicity is only part of the picture. There is also visibility. If a non-volatile (and non-synchronized) variable value is changed, other threads are not guaranteed to see the change in time, or at all.
Upvotes: 3
Reputation: 13841
Check http://www.javabeat.net/tips/169-volatile-keyword-in-java.html for understanding what volatile does. It avoids the intermediate thread cache but anyway there can be the lossed update from reading its value and updating in a non atomic operation.
Upvotes: 1
Reputation: 23219
You are correct. Because ++ is NOT an atomic operation you can still get inconsistent results where a thread reads/increments/writes a value at the same time as another thread.
Consider using AtomicInteger for cases like this.
Upvotes: 6