Имеем 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 произошел реордеринг. Итак, уважаемые знатоки, может ли такое иметь место? Что-то мне подсказывает, что не может, но доказать не могу. Прошу вашей помощи.