Search code examples
javathread-safetyjava-memory-modelsafe-publication

Safe initialisation of null reference


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?


Solution

  • 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.