Сообщение Re: Как работает SingleCheck в Dagger? от 15.01.2019 17:09
Изменено 15.01.2019 17:32 GarryIV
Re: Как работает SingleCheck в Dagger?
Здравствуйте, vsb, Вы писали:
vsb>Тут (метод get). Насколько я понимаю, это что-то вроде синглтона, но не гарантирующее единственный экземпляр, зато работающее чуть быстрей.
vsb>Меня смущает комментарий на 46-й строке: // The provider was null, so the instance must already be set
vsb>Т.е. они подразумевают, что если один поток выполнил инструкции в порядке
vsb>
vsb>то во втором потоке код
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 содержит значение из провайдера.
Все эти знания о кешах, барьерах и прочих регистрах нужны только для оптимизации.
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 содержит значение из провайдера.
Все эти знания о кешах, барьерах и прочих регистрах нужны только для оптимизации.
Re: Как работает SingleCheck в Dagger?
Здравствуйте, vsb, Вы писали:
vsb>Тут (метод get). Насколько я понимаю, это что-то вроде синглтона, но не гарантирующее единственный экземпляр, зато работающее чуть быстрей.
vsb>Меня смущает комментарий на 46-й строке: // The provider was null, so the instance must already be set
vsb>Т.е. они подразумевают, что если один поток выполнил инструкции в порядке
vsb>
vsb>то во втором потоке код
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.
Все эти знания о кешах, барьерах и прочих регистрах нужны только для оптимизации.
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.
Все эти знания о кешах, барьерах и прочих регистрах нужны только для оптимизации.