Безопасная инициализация нулевой ссылки - PullRequest
0 голосов
/ 25 сентября 2018

Мне интересно, какие гарантии публикации существуют для не конечного поля, инициализированного нулевым, если оно есть.

Рассмотрим следующий фрагмент:

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;
    }
}

Предполагая, что doSomething() всегдавызывается потоком 2, это безопасно?Какие гарантии дает то, что поток 2 увидит при первом обращении к нему?Есть ли вероятность того, что поток 2 увидит что-то ненулевое?

Где в JMM описана семантика этой ситуации?

Ответы [ 2 ]

0 голосов
/ 25 сентября 2018

JVM будет гарантировать, что вы не увидите из-под пустых значений , поэтому, кроме null , это невозможно , в случае, если Listне пустой (в этом примере, конечно).Если бы был задействован другой поток (скажем, Thread3), который изменит ваш список (добавит в него элементы), Thread2 сможет увидеть эти обновления.Просто отметьте, что отдельные методы CopyOnWriteArrayList являются потокобезопасными;ваш метод doSomething не является .

См. JLS для уточнения или отличного (и довольно сложного, может быть, только мне) Статья Алексея .

0 голосов
/ 25 сентября 2018

Говорить о безопасной публикации имеет смысл только тогда, когда вы инициализируете поле значимым объектом, который имеет состояние .Тогда неправильная публикация может привести к наблюдению частично построенного объекта .

В этом случае null не передает никакого состояния .Его можно считать неизменным объектом .Неизменяемые объекты не имеют проблем с публикацией.

Какие гарантии дает то, что поток 2 увидит при первом обращении к нему?

Поток 2 увидит nullпри обращении к i.ref.
Обратите внимание, что список может быть пустым, поскольку Поток 1, возможно, еще не добавил к нему Inner.

Есть ли вероятность того, что поток 2 увидит что-тоэто не ноль?

Нет.

...