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, а так как это отношение транзитивно, то другие потоки увидят уже правильное значение переменной.
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
17 апр. 2024, в 00:48
35000 руб./за проект
17 апр. 2024, в 00:13
800 руб./за проект
17 апр. 2024, в 00:06
240000 руб./за проект