Как работает SingleCheck в Dagger?
От: vsb Казахстан  
Дата: 15.01.19 13:55
Оценка:
Тут (метод get). Насколько я понимаю, это что-то вроде синглтона, но не гарантирующее единственный экземпляр, зато работающее чуть быстрей.

Меня смущает комментарий на 46-й строке: // The provider was null, so the instance must already be set

Т.е. они подразумевают, что если один поток выполнил инструкции в порядке
        this.instance = local;
        this.provider = null;

то во втором потоке код
      Provider<T> providerReference = this.provider;
      if (providerReference == null) {
        // The provider was null, so the instance must already be set
        local = this.instance;

отработает корректно. Для меня это не очевидно. Насколько я знаю, на x86 это может быть правдой, но на других архитектурах (например ARM) одно ядро процессора может видеть изменения памяти не в том порядке, в котором его делает другое ядро. Правда эти поля объявлены как volatile. Означает ли это, что JVM выставит все нужные барьеры и порядок изменения volatile-переменных будет одинаковым во всех ядрах без дополнительной синхронизации?
Отредактировано 15.01.2019 13:56 vsb . Предыдущая версия .
Re: Как работает SingleCheck в Dagger?
От: C0s Россия  
Дата: 15.01.19 15:03
Оценка: 10 (1) +2
Здравствуйте, vsb, Вы писали:

vsb>Правда эти поля объявлены как volatile. Означает ли это, что JVM выставит все нужные барьеры и порядок изменения volatile-переменных будет одинаковым во всех ядрах без дополнительной синхронизации?


должно быть именно так, но, (чисто чтобы набросить) только на тех сочетаниях ядер и ОС, для которых JVM прошла все стадии тестов и сертификаций
Re: Как работает SingleCheck в Dagger?
От: bzig  
Дата: 15.01.19 16:26
Оценка:
vsb>Насколько я понимаю, это что-то вроде синглтона, но не гарантирующее единственный экземпляр, зато работающее чуть быстрей.

А может и не быстрее. "synchronized (lock)" очень быстрый, когда только один поток синхронизируется (там запись ид потока в заголовок объекта), а у него там запись и чтение в volatile через строку.
Re: Как работает SingleCheck в Dagger?
От: GarryIV  
Дата: 15.01.19 17:09
Оценка: 10 (1) +1
Здравствуйте, vsb, Вы писали:

vsb>Тут (метод get). Насколько я понимаю, это что-то вроде синглтона, но не гарантирующее единственный экземпляр, зато работающее чуть быстрей.


vsb>Меня смущает комментарий на 46-й строке: // The provider was null, so the instance must already be set


vsb>Т.е. они подразумевают, что если один поток выполнил инструкции в порядке

vsb>
vsb>        this.instance = local; // A 
vsb>        this.provider = null; // B; A happens before B
vsb>

vsb>то во втором потоке код
vsb>
vsb>      Provider<T> providerReference = this.provider; // C; B happens before C => A happens before C
vsb>      if (providerReference == null) { 
vsb>        // The provider was null, so the instance must already be set
vsb>        local = this.instance; // D; A, B и C happens before D
vsb>


vsb>отработает корректно. Для меня это не очевидно. Насколько я знаю, на x86 это может быть правдой, но на других архитектурах (например ARM) одно ядро процессора может видеть изменения памяти не в том порядке, в котором его делает другое ядро. Правда эти поля объявлены как volatile. Означает ли это, что JVM выставит все нужные барьеры и порядок изменения volatile-переменных будет одинаковым во всех ядрах без дополнительной синхронизации?


В джаве вся конкаренси строися на happens before. В частности гарантируется что
* запись volatile переменной happens before ее чтения
* в рамках одного поток любая операция happens-before любой операции, следующей за ней, в исходном коде
* если A before B и B before C то A before C.

Применительно к данному случаю гарантируется что если мы видим null в provider то все можем быть уверены, instance содержит значение из провайдера. Но ,насколько я вижу тут нет гарантии, что instance проинициализируется только один раз. Зато lock-free.

Все эти знания о кешах, барьерах и прочих регистрах нужны только для оптимизации.
WBR, Igor Evgrafov
Отредактировано 15.01.2019 17:32 GarryIV . Предыдущая версия . Еще …
Отредактировано 15.01.2019 17:21 GarryIV . Предыдущая версия .
Отредактировано 15.01.2019 17:16 GarryIV . Предыдущая версия .
Re[2]: Как работает SingleCheck в Dagger?
От: GarryIV  
Дата: 15.01.19 17:38
Оценка:
Здравствуйте, bzig, Вы писали:

vsb>>Насколько я понимаю, это что-то вроде синглтона, но не гарантирующее единственный экземпляр, зато работающее чуть быстрей.


B>А может и не быстрее. "synchronized (lock)" очень быстрый, когда только один поток синхронизируется (там запись ид потока в заголовок объекта), а у него там запись и чтение в volatile через строку.


Во всех вызовах после инициализации будет только одно чтение volatile переменной.
WBR, Igor Evgrafov
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.