I have the below code
class VolatileCount {
volatile int count;
Object lock = new Object();
public void increment() {
synchronized (lock) {
count = count + 1;
}
System.out.print(" " + count);
}
}
If I call increment()
on same object from multiple threads I get the below output (might be different on your machine)
2 3 2 5 4 8 8 6 11 13 10 9 15 14 12 20 19
Looking at the repeating numbers I think happens-before seems to be broken, because considering first three number (2 3 2), if a thread sees 3 , increment has happened and since the variable is volatile, its value should be 3 or more but cannot be 2 in any thread.
However, the print line seems to have been reordered here, is it correct to reorder that line? What am I missing here? I run on JDK 7 (Eclipse)
Update
Because you seem to want an explanation for the specific case of "2 3 2"
i
(now 1)i
(now 2)i
(X loads 2)i
(Y loads 2)i
, reads i
, prints i
(prints 3)The point is: System.out.print(" " + count)
isn't atomic. The thread can be preempted after performing a volatile read and before printing the value.
If you want to prevent duplicate values from being printed, you have to perform the volatile read inside the lock:
public void increment() {
int localCount;
synchronized (lock) {
count = count + 1;
localCount = count; // volatile load
}
System.out.print(" " + localCount);
}
This wouldn't prevent values from being printed out of order though. In order to print them in order, without duplicates, you'd have to move the print
into the lock as well.
The print statement is outside the lock. Consider the code running inside System.out.print(" " + count)
.
i
print
arguments and performs a volatile read on the count
variable, and loads the value 2
.i
i
(which is now 3
), calls the print method which runs to completion.print
to completion, which prints 2.This would make the numbers show out of order, such as "3 2 4".
Some numbers might also be repeated when:
i
(which is now 2)i
(which is now 3)i
(which is 3)i
(which is 3)Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments