|
|
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
Предположим, что мы написали data race free программу. То есть все куски кода их разных потоков общаются друг с другом исключительно через synchronized-with, и всегда видят актуальные значения. Вопрос такой: существует ли data race free программа, которая не сможет корректно работать без модификатора final? Ну то есть взяли, например, и выпилили final из Java 8. Пострадает ли от этого хоть одна data race free программа? P.S.: Вопрос касается final исключительно в контексте concurreny. Другие плюшки вроде complie-time проверок и inner классов оставим за скобками. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 00:28 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
ну по-моему довольно очевидно, что любую синхронизацию, можно обернуть synchronized(lock), так что вопрос изначально немного лишен смысла. Вы видели в какой-либо книге классической по concurrency понятие final? А вот вопрос удобства и полезности - тут можно дискутировать, да. Основная фишка final в гарантированной безопасной публикации, сделал одну ссылку final и весь граф объектов гарантировано безопасно опубликован. Как-то так считаю ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 06:22 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
забыл ник , Я не говорил про synchronized , я говорил про synchronized-with , это разные вещи. То есть у нас есть корректно синхронизированная программа, без гонок. Она работает. Теперь мы берем, и выпиливаем все final. Будет ли она работать и дальше? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 07:54 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
cdtyjv, Простите, Вы про warning "Synchronization on non-final field", который вывешивает IDE? Так это не более чем совет, наряду стем, что строку лучше не использовать как монитор. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 09:30 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньев , Нет, я не про это. Я про использование final в корректно синхронизированном коде. Моя идея очень проста - с точки зрения многопоточности, final нужен только в некорректно синхронизированном коде, то есть в коде, где есть data race. Приведу пример. Есть программка с некорректной публикацией: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. Мы добавили final, но программа все равно не работает. Не работает она по причине наличия data race на переменной holder, и читатель не может увидеть ее изменение. Программа некорректна. Окей, я могу это легко исправить, сделав holder volatile: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. Таким образом, я делаю вывод, что final нужен только в тех случаях, если у нас уже был какой-то косяк в коде, и мы хотим немного его подшлифовать. Если же у нас код корректен, то final не нужен никогда. Пример такого сознательного "косяка" - double checked locking, когда мы сознательно оставляем в коде data race, но при подозрении на его возникновение всегда можем грамотно разрулить ситуацию через тот же final, например. P.S.: Повторюсь, я говорю про final сейчас исключительно в контексте многопоточности . P.S ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 10:34 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
Надо посмтреть спецификацию jvm и сравнить все, что касается многопоточности волатилов и финалов. Если волатил ганатирует все что финал или больше, то да, в контексте многопоточности финал не нужен. но навскидку, финал дает меньше гарантий, в часности если есть final MyObj x; MyObj z; z=new MyObj(10); x=new MyObj(15); То другой поток может не увидеть z= MyObj(10), но увидеть x=MyObj(15) а так же увидеть все x.* А если х будет волатил, то видимость z=MyObj(10) гарантируется. Поэтому, навкидку (и в контексте многопоточности), финал можно безопасно заменить волатилом, а волатилы финалом - нет. Но мое мнение не окончательное. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 11:32 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
cdtyjvА теперь вопрос: а нахрена нам теперь нужен final у Holder.val? Поскольку Вы сделали holder volatile, то согласно JMM начиная с 1.5 есть ,есть барьер на операции с памятью, который вроде бы гарантирует окончание конструктора до присвоения, а соответственно до чтения (либо null либо отработавший конструктор). Присвоение final полям значений меняет порядок их назначения. См. http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2 Если внимательно присмотреться к шагам, то можно увидеть когда именно захватывается-отпускается блокировка (а значит появляется барьер последовательности выполнения). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 11:32 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
chabapokЕсли волатил ганатирует все что финал или больше, то да, в контексте многопоточности финал не нужен. С одной стороны больше... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 11:33 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
chabapokА если х будет волатил, то видимость z=MyObj(10) гарантируется.Это не так. Давайте посмотрим на такой вот код: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Давайте рассмотрим, как отработает последняя строчка в идеальных условиях, когда у нас нет out-of-order execution: ref = allocate(MyObject); ref.x = 1; ref.y = 2; // За volatile store идет "барьер сверху". _________ --------- obj = ref; "Барьер сверху" означает, что присвоение x не может убежать за присвоение y. Однако, следующий вариант также является абсолютно валидным с точки зрения JMM: ref = allocate(MyObject); ref.x = 1; obj = ref; ref.y = 2; _________ --------- Таким образом мы увидим объект до того, как была инициализирована его волатильная переменная. Так что volatile и final нельзя сравнивать в таком ключе. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 11:48 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевПоскольку Вы сделали holder volatile, то согласно JMM начиная с 1.5 есть ,есть барьер на операции с памятью, который вроде бы гарантирует окончание конструктора до присвоения, а соответственно до чтения (либо null либо отработавший конструктор).Нет такой гарантии в JMM. Шипилев недавно поднимал эту тему в concurrency-interest, предлагая сделать такую гарантию для volatile, но ее зарубили - http://cs.oswego.edu/pipermail/concurrency-interest/2013-November/011951.html ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 12:03 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
cdtyjvТаким образом мы увидим объект до того, как была инициализирована его волатильная переменная. Так что volatile и final нельзя сравнивать в таком ключе. Вообще говоря и final гарантирует это не всегда. Только если конструктор не публикует свое this. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 12:47 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
cdtyjvНет такой гарантии в JMM. Вы путаете волатильное поле создаваемого объекта с волатильной переменной, которой присваивают создаваемый объект. На Вашем примере - если бы val был волатильным, а холдер нет - была бы гонка. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 12:52 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
хотя я тоже тут плаваю - поэтому написал вроде бы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 12:54 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
Сергей АрсеньевВообще говоря и final гарантирует это не всегда. Только если конструктор не публикует свое this.Если разработчик объявил поле final, а потом отдал this из конструктора до его инициализации, то это проблема разработчика, а не final. final дает четкие гарантии при его корректном использовании. Я с таким же успехом могу вам сказать, что synchronized не всегда гарантирует критическую секцию, если использовать разные мониторы. Еще раз - я говорю про корректно синхронизированную программу, где все инструменты использованы корректно. И я пришел к выводу, что в таких программах final не нужен. У кого есть другие мысли по этому поводу? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 12:57 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
Сергей Арсеньев Вы путаете волатильное поле создаваемого объекта с волатильной переменной, которой присваивают создаваемый объект.Да, я не правильно вас понял. Ваше утверждение верно. Мой поинт как раз в этом и заключается, что если гонок нет, то для final просто напросто нет применений. А если гонка все таки есть, то final никогда не избавит нас от нее, но лишь даст немного более предсказуемые результаты. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 13:01 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
cdtyjvА если гонка все таки есть, то final никогда не избавит нас от нее, но лишь даст немного более предсказуемые результаты. Ну почему же, большинство народу сходится во мнении, что публикование через Holder (static final) не менее правильно чем dcl с volatile. Да и проще. Просто любую задачу можно решать по разному. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 13:20 |
|
||
|
Нужен ли final в корректно синхронизированных программах?
|
|||
|---|---|---|---|
|
#18+
cdtyjv Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. ... ref = allocate(MyObject); ref.x = 1; obj = ref; ref.y = 2; Таким образом мы увидим объект до того, как была инициализирована его волатильная переменная. Так вы ж привели изначально не data race free код, что противоречит условию задачи топикстартера! Поэтому ваш пример не равен моему, и потому он ничего не опровергает. В рамках моего примера и вашего кода (при условии многопоточного доступа к obj), волатильной или финальной надо рассматривать obj, а не obj.y. А если многопоточного доступа к obj нету, тогда его вообще можно не рассматривать, и тогда ваш пример просто вырождается в мой. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.02.2014, 13:49 |
|
||
|
|

start [/forum/topic.php?fid=59&fpage=187&tid=2127694]: |
0ms |
get settings: |
9ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
41ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
55ms |
get tp. blocked users: |
2ms |
| others: | 240ms |
| total: | 381ms |

| 0 / 0 |
