Safe initialisation of null reference

74 views Asked by At

I'm wondering what publication guarantees exist for a non-final field initialised to null, if any.

Consider the following snippet:

public class MyClass {

    private final CopyOnWriteArrayList<Inner> list = new CopyOnWriteArrayList<>();

    //called by thread 1
    public void init() {
        // initialise Inner instance
        list.add(new Inner());
    }

    //called by thread 2
    public void doSomething() {
        for (Inner i : list) {
            // access non-final field
            Object ref = i.ref;
            // do something
            // ...
            // ...

            // potentially set i.ref
        }
    }

    private static class Inner {
        // initialised by thread 1
        Object ref = null;
    }
}

Assuming doSomething() is always called by thread 2, is this safe? What guarantees are made about what thread 2 will see the first time it's accessed? Is there any possibility thread 2 would see something that's non-null?

Where in the JMM are the semantics around this situation described?

2

There are 2 answers

6
Eugene On BEST ANSWER

JVM will guarantee that you don't see out of thin air values, so anything other than null it not possible, in case that List is not empty (in this example, of course). If there would have been a different thread involved (let's say Thread3) that would alter your list (add elements to it), Thread2 could see those updates. Just note that individual methods of CopyOnWriteArrayList are thread safe; your method doSomething is not.

See the JLS for the specifics or the excellent (and rather complicated, may be just to me) Aleksey article.

1
Andrew Tobilko On

Talking about safe publication makes sense only when you are initialising a field with a meaningful object that has the state. Then, improper publication may lead to observing a partially constructed object.

In this case, null doesn't convey any state. It can be considered an immutable object. Immutable objects don't have publication problems.

What guarantees are made about what thread 2 will see the first time it's accessed?

Thread 2 will see null when referring to i.ref.
Note that the list may be empty because Thread 1 may not have added an Inner to it yet.

Is there any possibility thread 2 would see something that's non-null?

No.