2013-07-04 9 views
3
@Singleton 
@LocalBean 
@Startup 
@ConcurrencyManagement(ConcurrencyManagementType.BEAN) 
public class DeliverersHolderSingleton { 

    private volatile Map<String, Deliverer> deliverers; 

    @PostConstruct 
    private void init() { 
     Map<String, Deliverer> deliverersMod = new HashMap<>(); 
     for (String delivererName : delivererNames) { 
      /*gettig deliverer by name*/ 
      deliverersMod.put(delivererName, deliverer); 
     } 
     deliverers = Collections.unmodifiableMap(deliverersMod); 
    } 

    public Deliverer getDeliverer(String delivererName) { 
     return deliverers.get(delivererName); 
    } 

    @Schedule(minute="*", hour="*") 
    public void maintenance() { 
     init(); 
    } 
} 

Singleton используется для хранения данных. Данные обновляются один раз в минуту. Возможно ли, что чтение из unmodifiableMap будет проблемой с синхронизацией? Возможно ли, что произойдет переупорядочение в методе init и будет опубликована ссылка на сборник, но сбор не заполняется полностью?Параллельный доступ к unmodifiableMap

+2

Я предполагаю, что решающая проблема заключается в том, является ли возвращение метода '@ PostConstruct'« безопасной публикацией »данных, установленных там. – Raedwald

+0

Если мы предположим, что это не так, будут выставлены наполовину построенные бобы, это будет довольно большой недостаток дизайна, который укусит вас в a ** в нескольких местах. – Kayaman

+0

'volbers' volatile должен предотвращать переупорядочение, и ваш класс должен работать должным образом (предполагая, что * получение поставщика по имени * является безопасным потоком). – assylias

ответ

3

Модель памяти Java гарантирует, что there is a happens-before relationship between a write and a subsequent read to a volatile variable. Другими словами, если вы пишете переменную volatile и впоследствии читаете эту же переменную, у вас есть гарантия, что операция записи будет видна, даже если задействовано несколько потоков:

Запись в нестабильное поле (§8.3.1.4) - до каждого последующего чтения этого поля.

Он идет дальше и гарантирует, что любая операция, которая была до операции записи также будет видна в момент чтения (благодаря правилу порядка программы, и тот факт, что происходит, прежде, чем отношение транзитивности).

Ваш метод getDeliverers читается из изменчивой переменной, поэтому он увидит последнюю запись, записанную на линии deliverers = Collections.unmodifiableMap(deliverersMod);, а также предыдущие операции, в которых заполняется карта.

Таким образом, ваш код является потокобезопасным, и ваш метод getDeliverers вернет результат на основе последней версии вашей карты.

0

вопросы безопасности Thread здесь:

  • несколько операций чтения из HashMap - это поточно, потому что несколько операций чтения допускаются до тех пор, пока нет изменений в коллекции и записывает в HashMap не произойдет, потому что карта является unmodifiableMap()

  • чтения/записи на deliverers - это поточно, потому что все ссылки на Java назначения являются неделимыми

Здесь я не вижу никаких небезопасных операций.

Я хотел бы отметить, что имя метода init() вводит в заблуждение, это предполагает, что он вызывается один раз во время инициализации; Я бы предложил позвонить ему rebuild() или recreate().

+0

Возможно ли, что ссылка будет опубликована до того, как коллекция будет инициализирована из-за переупорядочения? – shurik2533

+0

@ shurik2533 Если бы это было так, я считаю, что программирования вообще не будет смысла - [* компиляторам разрешено изменять порядок инструкций в любом потоке, если это не влияет на выполнение этого потока в изоляции *] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html) – Dariusz

+0

@Dariusz Имеются исправления, которые не влияют на выполнение в однопоточном режиме, но влияют на многопоточную программу. Например, перемещение 'deliverers = Collections.unmodifiableMap (deliverersMod);' перед циклом. – assylias

1

Согласно Переупорядочению сетки здесь http://g.oswego.edu/dl/jmm/cookbook.html, то первая операция является Normal Store не может быть заказан с второй операцией будучи Volatile Store, так что в вашем случае, до тех пор, как неизменная карта не равно нуль, то не было бы каким-либо переназначение проблемы.

Кроме того, все записи, которые происходят до энергозависимого хранилища, будут видны, поэтому вы не увидите никаких проблем с публикацией.

Смежные вопросы