nikdeapen
nikdeapen

Reputation: 1601

Java Memory Visibility In Constructors

For the following simplified class:

public class MutableInteger {
    private int value;
    public MutableInteger(int initial) {
        synchronized(this) { // is this necessary for memory visibility?
            this.value = initial;
        }
    }
    public synchronized int get() {
        return this.value;
    }
    public synchronized void increment() {
        this.value++;
    }
    ...
}

I guess the general question is for mutable variables guarded by synchronization is it necessary to synchronize when setting the initial value in the constructor?

Upvotes: 7

Views: 1200

Answers (2)

psaw.mora
psaw.mora

Reputation: 958

Though you've accepted an answer, let me add my two cents. Based on what I've read, synchronization or making the field volatile would not grantee the following visibility.

A thread T1 may see a not-null value for this, but unless you've made the field value final, there's a good chance of thread T1 seeing the default value of value.

The value could be a volatile or been accessed within synchronized blocks (monitor acquire and release), either way provided that the correct execution order was followed, there's happens-before edge from the write to the read of value. There's no argument on that. But it's not the happens before edge that we have to consider here, but the correct publication of the object itself(MutableInteger). Creating an object is twofold where the JVM first allocates a heap space and then start initializing fields. A thread may see a not-null reference of an object but an uninitialized field of that as long as the said field is not final (Assuming reference has been correctly published).

Upvotes: 0

biziclop
biziclop

Reputation: 49804

You're right, without the synchronized block in the constructor there is no visibility guarantee for non-final fields, as can be seen in this example.

However in practice I would rather use volatile fields or the Atomic* classes in situations like this.

Update: It is also important to mention here that in order for your program to be correctly synchronized (as defined by the JLS), you will need to publish the reference to your object in a safe manner. The cited example doesn't do that, hence why you may see the wrong value in non-final fields. But if you publish the object reference correctly (i.e. by assigning it to a final field of another object, or by creating it before calling Thread.start()), it is guaranteed that your object will be seen at least as up-to-date as the time of publishing, therefore making the synchronized block in the constructor unnecessary.

Upvotes: 4

Related Questions