|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
P.S. я знаю, что не надо использовать DCL. интерес сугубо академический. Решил изучить таки первоисточник с описанием проблемы DCL: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html Вот есть такой код: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Ну и как мне уже давно известно это не будет работать потому, что поток, который не входит в критическую секцию может увидеть helper уже не null, но конструктор Helper ещё не закончился. Всё вроде ясно кроме одной детали. А что если конструктор пустой? в этом случае проблема тоже будет? Также там пишут, что авторAlthough the double-checked locking idiom cannot be used for references to objects, it can work for 32-bit primitive values (e.g., int's or float's). Note that it does not work for long's or double's, since unsynchronized reads/writes of 64-bit primitives are not guaranteed to be atomic. И мол вот так работать будет: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
Но что-то я ума не приложу почему. Вот допустим первый тред выполнил строку Код: java 1.
Второй тред может увидеть, что эта строка выполнилась, но при этом не увидеть предыдущие две строки. Но в этом случае я вообще хз что он может увидеть. По всей видимости тут оптимизации сработать не должны. Только я не понимаю почему. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 15:42 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
questionerВторой тред может увидеть, что эта строка выполнилась, но при этом не увидеть предыдущие две строки. Но в этом случае я вообще хз что он может увидеть. По всей видимости тут оптимизации сработать не должны. Только я не понимаю почему. Раз не null - значит результат подсчитан Поскольку он int, он атомарный (т.е. не может быть не до конца записанный/подсчитанный /в отличие от объекта/) Т.ч. "не увидить предыдущие две строки" он физически не может. Что значет "не увидеть", когда результат уже есть и он корректный (т.к. атомарный) IMHO Хороший вопрос Вы задали, эта хренотень с непольностью проинициализированными объектами мне вообще не понятна (((, в свое время дофига времени потерял на отладке проекта, где это вылезало AFAIK Если класс объявлен как имутабельный, то вроде конструктор гарантирует атомарность инициализацию объекта и такой хренотени быть не должно, надеюсь точную ссылку на доку кто нибудь сможет дать, у меня под рукой нет ... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 16:25 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
Leonid Kudryavtsev, спасибо за ответ Leonid KudryavtsevAFAIK Если класс объявлен как имутабельный, то вроде конструктор гарантирует атомарность инициализацию объекта и такой хренотени быть не должно, надеюсь точную ссылку на доку кто нибудь сможет дать, у меня под рукой нет Примерно по поводу этого из той же статьи: авторIn fact, assuming that the computeHashCode function always returned the same result and had no side effects (i.e., idempotent), you could even get rid of all of the synchronization. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 16:45 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
questioner Примерно по поводу этого из той же статьи: авторIn fact, assuming that the computeHashCode function always returned the same result and had no side effects (i.e., idempotent), you could even get rid of all of the synchronization. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Если операция идемпотентна и атомарна как в этом случае - то зачем вообще может понадобиться синхронизация? Что-то или кто-то недоговаривает. Для начала надо определиться что этот код вообще должен делать? Считать хэшкод один раз? Считать несколько но главное чтобы корректно? Или еще что? А что если хэшкод вернет 0, автор не подумал? Короче я не понимаю идею, что вообще хочется понять то? ... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 16:53 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
забыл никquestionerПримерно по поводу этого из той же статьи: пропущено... Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Если операция идемпотентна и атомарна как в этом случае - то зачем вообще может понадобиться синхронизация? Что-то или кто-то недоговаривает. Для начала надо определиться что этот код вообще должен делать? Считать хэшкод один раз? Считать несколько но главное чтобы корректно? Или еще что? А что если хэшкод вернет 0, автор не подумал? Короче я не понимаю идею, что вообще хочется понять то? Закешировать наверное хотят, но я лично не могу понять действительно ли это выполнится только один раз или имеется ввиду, что выполнится и выполнится, всё равно одно и то же вернёт. На ноль решили забить - Шипилёв чо то такое кстати рассказывал кстати применительно к Strring- реально не большая проблема. Статья - классика. авторSigned by: David Bacon (IBM Research) Joshua Bloch (Javasoft), Jeff Bogda, Cliff Click (Hotspot JVM project), Paul Haahr, Doug Lea, Tom May, Jan-Willem Maessen, Jeremy Manson, John D. Mitchell (jGuru) Kelvin Nilsen, Bill Pugh, Emin Gun Sirer Не самые последние люди в java сообществе. Не находите? ... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 17:02 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
questionerзабыл никпропущено... Если операция идемпотентна и атомарна как в этом случае - то зачем вообще может понадобиться синхронизация? Что-то или кто-то недоговаривает. Для начала надо определиться что этот код вообще должен делать? Считать хэшкод один раз? Считать несколько но главное чтобы корректно? Или еще что? А что если хэшкод вернет 0, автор не подумал? Короче я не понимаю идею, что вообще хочется понять то? Закешировать наверное хотят, но я лично не могу понять действительно ли это выполнится только один раз или имеется ввиду, что выполнится и выполнится, всё равно одно и то же вернёт. На ноль решили забить - Шипилёв чо то такое кстати рассказывал кстати применительно к Strring- реально не большая проблема. Статья - классика. авторSigned by: David Bacon (IBM Research) Joshua Bloch (Javasoft), Jeff Bogda, Cliff Click (Hotspot JVM project), Paul Haahr, Doug Lea, Tom May, Jan-Willem Maessen, Jeremy Manson, John D. Mitchell (jGuru) Kelvin Nilsen, Bill Pugh, Emin Gun Sirer Не самые последние люди в java сообществе. Не находите? Статья была написана для java 1.4, я понимаю что ты некромант, но все же. Если computeHashCode вернет 0 - то у этого куда ни при каких раскладах нет шансов выполниться всего лишь раз ... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 17:06 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
забыл никquestionerпропущено... Закешировать наверное хотят, но я лично не могу понять действительно ли это выполнится только один раз или имеется ввиду, что выполнится и выполнится, всё равно одно и то же вернёт. На ноль решили забить - Шипилёв чо то такое кстати рассказывал кстати применительно к Strring- реально не большая проблема. Статья - классика. пропущено... Не самые последние люди в java сообществе. Не находите? Статья была написана для java 1.4, я понимаю что ты некромант, но все же. Если computeHashCode вернет 0 - то у этого куда ни при каких раскладах нет шансов выполниться всего лишь раз Я ж писал, что интерес академический. Конкретно в этом примере разница есть 11 это джава или 4-ая ? забыл никЕсли computeHashCode вернет 0 - то у этого куда ни при каких раскладах нет шансов выполниться всего лишь раз Да я тебя понял. Вероятность такого хешкода ничтожно мала и можно просто принять тот факт, что для такого хешкода мы будем пересчитывать. вот кстати String#hashCode из java 11 Код: java 1. 2. 3. 4. 5. 6. 7. 8.
... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 17:14 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
questionerЯ ж писал, что интерес академический. Конкретно в этом примере разница есть 11 это джава или 4-ая ?там внизу же написано все: кто final не использует в синглетонах - тот лох, а по факту в java 5 для volatile запретили reordering и статья об этом. questionerДа я тебя понял. Вероятность такого хешкода ничтожно мала и можно просто принять тот факт, что для такого хешкода мы будем пересчитывать.У меня в приложении наверное процентов 10 строк пустые, ничтожность аж зашкаливает. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 17:26 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
questioner Конкретно в этом примере разница есть 11 это джава или 4-ая ? Есть, начиная с 5 java - разработчики дали нам solid JMM, которой нао следовать и это гарантирует что твой код будет работать. В 4-ке такой возможности не было ... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 17:28 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
забыл никЕсли операция идемпотентна и атомарна как в этом случае - то зачем вообще может понадобиться синхронизация? Слова "идемпотентна" я не знаю ))) А синхронизация в любом случае требуется. Или volatile или synchronize в любом случае должно быть. IMHO & AFAIK note: в какой-то момент из примеров кода в данной ветке и volatile и synchronize исчезло. IMHO без них не корректно в любом случае. забыл никКороче я не понимаю идею, что вообще хочется понять то? Как я понимаю, главные поинт в начальном топике: Что объекты НЕ атомарны (в "новых" Java вроде для имутабельных объектов сделали исключение) - и такие финты ушами с объектами НЕ прокатывают. На эту хренотень с объектами на реальном проекте я и сам нарывался, но честно говоря, в голове плохо укладывается. как после физического завершения конструктора объект все еще не проинициализирован. Тут у меня шарики за ролики заезжают и на понятном, "бытовом" языке IMHO это не объяснимо. Надо переставать мыслить терминами "завершилось"/"увидело" и мыслить только абстрактно в терминах "happens before", что лично для меня достаточно тяжело. IMHO & AFAIK ... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 17:33 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
забыл никsolid JMM кидай ссылки на доку, т.к. google например по "solid JMM" находит чисто мусор и зубную пасту ((( ... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 17:34 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
Андрей ПанфиловКонкретно в этом примере разница есть 11 это джава или 4-ая ?там внизу же написано все: кто final не использует в синглетонах [/quot] Да я тебе больше скажу - кто синглтоны пишет тоже лох. Андрей ПанфиловУ меня в приложении наверное процентов 10 строк пустые, ничтожность аж зашкаливает. Это тебе к Шипилёву. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 17:48 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
[quot Андрей Панфилов]questionerтам внизу же написано все: кто final не использует в синглетонах - тот лох http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html If Helper is an immutable object, such that all of the fields of Helper are final, then double-checked locking will work without having to use volatile fields. The idea is that a reference to an immutable object (such as a String or an Integer) should behave in much the same way as an int or float; reading and writing references to immutable objects are atomic. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.09.2019, 17:53 |
|
Почему DCL без volatile работает для 32-bit примитивов ?
|
|||
---|---|---|---|
#18+
questionerВторой тред может увидеть, что эта строка выполнилась, но при этом не увидеть предыдущие две строки. Но в этом случае я вообще хз что он может увидеть. По всей видимости тут оптимизации сработать не должны. Только я не понимаю почему. Треды не видя строки кода, они видят только данные. Все проблемы синхронизации проще всего описать в терминах двух процессоров с кэшами. Первый записал значение в КЭШ, второй прочитал свой кэш- и что там у него- фиг знает. Объясняя неточно, но понятно: Вход в synchronized секцию и чтение volatile гарантируют, что все наши кэши обновлены. Выход из synchronized и запись volatile - гарантируют, что мы все кэши сбросили. Но при этом в варианте с объектом до проверки if (helper == null) нет никакой синхронизации и в "наш" кэш может приехать только ссылка, но не доехать объект (или приехать только его часть). Для этого нужен volatile - он гарантирует, что до нас доедет только всё целиком. А когда нам нужно только один примитив- то всё просто- он либо есть, либо его нет. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.09.2019, 10:11 |
|
|
start [/forum/topic.php?fid=59&msg=39864134&tid=2121109]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
51ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
49ms |
get tp. blocked users: |
1ms |
others: | 13ms |
total: | 155ms |
0 / 0 |