Re: unable to synchronize on primitive wrapper class?
Eniac Zhang wrote:
Hi all,
My colleague and I found this while debugging our program. We created a
simple program to duplicate the issue. So here's the program:
public class VolatileVar {
static class Worker implements Runnable {
public static Integer total = 0;
public static Object dummy = new Object();
public int count = 0;
public void run() {
while (!Thread.interrupted()) {
synchronized (total) {
total++;
You have been fooled by "auto-boxing," an evil addition
to Java that was intended to make it easier to use but in
actuality just makes it more confusing.
Keep in mind that operators like `++' work on primitive
variables, not on objects like Integer instances. The compiler
has actually translated `total++;' as if you had written
total = new Integer(total.intValue() + 1);
.... or perhaps it uses Integer.valueOf() instead of calling the
constructor; I'm not certain. Either way, `total' after this
assignment refers to a different Integer instance than the one
the code synchronizes on -- and the accesses to the `total'
reference itself are not synchronized at all. So when multiple
threads execute this code you have race conditions; the outcome
will be (in general) unpredictable.
Some of the features added in Java 1.5 were, I think, Good
Things. Auto-boxing and auto-unboxing, IMHO, are Bad Things
because they lead to confusions of just the kind you've fallen
victim to. I wish they had not been invented.
--
Eric Sosman
esosman@ieee-dot-org.invalid