shurik2533
@shurik2533

Реордеринг при публикации ссылки на UnmodifiableMap?

Имеем EJB Singleton. В нем после создания объекта (но до публикации) запускается метод rebuild(), помеченный аннотацией @PostConstruct. Имеем шедулер, который запускает этот же метод раз в минуту. Метод инициализирует коллекцию, обворачивает в UnmodifiableMap и размещает через volatile в переменную deliverers.



Так же имеем публичный метод getDeliverer, который в другом потоке читает данные из UnmodifiableMap deliverers.



@Singleton<br>
@LocalBean<br>
@Startup<br>
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)<br>
public class DeliverersHolderSingleton {<br>
<br>
    private volatile Map<String, Deliverer> deliverers;<br>
<br>
    @PostConstruct<br>
    private void rebuild() {<br>
        Map<String, Deliverer> deliverersMod = new HashMap<>();<br>
        for (String delivererName : delivererNames) {<br>
            /*gettig deliverer by name*/<br>
            deliverersMod.put(delivererName, deliverer);<br>
        }<br>
        deliverers = Collections.unmodifiableMap(deliverersMod);<br>
    }<br>
<br>
    public Deliverer getDeliverer(String delivererName) {<br>
        return deliverers.get(delivererName);<br>
    }<br>
<br>
    @Schedule(minute="*", hour="*")<br>
    public void maintenance() {<br>
        rebuild();<br>
    }<br>
}<br>




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

Например, поток A, в котором вызывается метод init(), сначала присвоит ссылку на UnmodifiableMap переменной deliverers (публикация самой ссылки пройдет безопасно, т.к. volatile), а после этого выполнит инициализацию нашего UnmodifiableMap.



Это, как мне кажется, не противоречит Java Memory Model. Cпецификация говорит, что компилятор позволяет делать перестановку инструкций в любом потоке, если это не влияет на выполнение этого потока в изоляции («compilers are allowed to reorder the instructions in either thread, when this does not affect the execution of that thread in isolation»). В данном случае никакого влияния нет и перестановка представляется возможной, как мне показалось.



Так вот, поток B вызывает метод getDeliverer в тот момент, когда ссылка на UnmodifiableMap уже присвоена, но сама коллекция видится ему не достроенной, т.к. в потоке A произошел реордеринг. Итак, уважаемые знатоки, может ли такое иметь место? Что-то мне подсказывает, что не может, но доказать не могу. Прошу вашей помощи.
  • Вопрос задан
  • 3213 просмотров
Пригласить эксперта
Ответы на вопрос 1
@Artyushov
Так как volatile write и volatile read находятся в отношении happens-before, поток, читающий значение, увидит все действия, которые делал поток, вызвавший rebuild(), до volatile write. То есть внутри одного потока все операции находятся в отношении happens-before, а так как это отношение транзитивно, то другие потоки увидят уже правильное значение переменной.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы