Справочная аннотация в поле пакета

Я разрабатываю приложение с OSGi. Изучая компендиум OSGi 6.0 (раздел 112.8.1) I наткнулся на декларативный сервис; в частности я посмотрел следующий абзац:

Для поля значения по умолчанию для аннотации ссылки:

  • Имя метода или поля привязки используется в качестве имени ссылки.
  • Мощность 1:1, если поле не является коллекцией. 0..n мощность, если поле является коллекцией.
  • Статическая неохотная политика, если поле не объявлено изменчивым. Динамическая неохотная политика, если поле объявлено изменчивым
  • Запрашиваемая услуга является типом поля.

Например:

@Reference
volatile Collection<LogService> log;

Теперь я прочитал из OSGi Нила Бартлетта на практике (раздел 11.10.2), что синхронизация и параллелизм Методы bind и unbind Reference annotation немного сложны (особенно в сценариях динамической политики). В частности, потокобезопасным примером ссылки на службу через аннотацию может быть:

@Component( provide = MailboxListener.class, properties = { "service.ranking = 10"})
public class LogMailboxListener implements MailboxListener {
    private final AtomicReference<Log> logRef = newAtomicReference <Log> () ;

    public void messagesArrived ( String mboxName, Mailbox mbox, long [ ] ids ) {
        Log log = logRef.get();
        if (log != null ) 
            log.log(Log.INFO, ids.length + "message(s) arrived in mailbox " + mboxName, null);
        else
            System.err.println("No log available!");
    }

    @Reference( service = Log.class, dynamic = true, optional = true )
    public void setLog(Log log) {
        logRef.set(log);
    }

    public void unsetLog(Log log) {
        logRef.compareAndSet(log, null);
    }
}

Я думаю, что понял из книги, почему динамическая политика нуждается в этих настройках из многопоточного сценария. У меня такой вопрос: если бы аннотация ссылки находилась в поле (декларативная служба 1.3), как я мог бы добиться потокобезопасности? Только определив ссылку как «изменчивую» (как предполагает компендиум)? Или есть какая-то хитрая часть, которая создаст проблемы в приложении?

Спасибо за любой ответ


person Koldar    schedule 21.10.2016    source источник


Ответы (1)


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

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

person BJ Hargrave    schedule 21.10.2016
comment
Итак, чтобы использовать ссылку на пакет с аннотацией поля, мне нужно, когда мне нужно использовать саму ссылку, использовать само поле (а не локальную копию, например LogService a = this.log)? Позвольте мне привести пример (для простоты я буду использовать простой LogService вместо их набора): public void foo() { if (this.log != null) { this.log.log("foo started"); //do other code } Является ли это потокобезопасным с полем log, просто установленным в volatile? Или нужны дальнейшие операции? - person Koldar; 23.10.2016
comment
Когда вам когда-либо понадобится использовать службу журналов, скопируйте ее в локальную переменную из поля, используйте локальную переменную, а затем позвольте локальной переменной выйти из области действия. Моя цель заключалась не в том, чтобы скопировать его из поля в какое-то другое место, которое удерживается в течение длительного времени (например, другой объект). - person BJ Hargrave; 23.10.2016
comment
@BJHargave А, хорошо, теперь я понял! Я прочитал на практике ту же самую процедуру, которую вы только что написали в OSGi Нила, но из вашего комментария я ошибочно подумал, что вы предложили избегать использования локальной переменной. Теперь все совершенно ясно! Я боялся, что написание ссылок на потокобезопасные сервисы будет отличаться от использования аннотированного поля, но, по-видимому, все намного проще! Мне даже не нужны AtomicReference или проверки null внутри метода unbind. Похоже, что современные ссылки OSGi должны использовать как можно больше версии DS с полевыми аннотациями, а не метод привязки/отвязки, верно? - person Koldar; 23.10.2016
comment
В той степени, в которой реализация вашего компонента не требует уведомления об изменениях в связанных службах (как вы могли бы получить с вызовами методов привязки и развязки), тогда да, использование ссылок на поля намного проще и менее подвержено ошибкам. - person BJ Hargrave; 24.10.2016