|
|
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
Ох "не бейте" меня, друзья и коллеги. В джава я новичок, поэтому возможно задаю глупые вопросы, но очень хочу разобраться. Вводная. Есть необходимость написать многопоточное приложение, которое будет работать на Java. Собственно все бы ничего, но углубляясь в тему, а я ведь хочу написать хорошо и правильно, приобрести положительный опыт, и, главное, чтобы приложение не требовало сразу же рефакторинга. Приложение будет выполнять определенные бизнес-задачи, читателей будет много, писатель один, и писать он будет нечасто относительно количества чтений. Теперь суть. Книгу Java. Concurrency in practice только просматривал, грешен, целиком не прочел. Видимо стоит. Читал форумы и статьи о много поточности, пришел к выводу, что есть замечательный фреймворк java.util.concurrency, в котором мне, человеку из мира C#, близким показался класс ReentrantReadWriteLock. Тут как-раз предоставляется возможность читать нескольким читателям, пока не пишет писатель. Набросал я маленький проект для проверки производительности, а какая из реализаций синхронизации показывает себя лучше? Запускал на машине с Windows 7, процессор Intel i5 5570. Java 1.8. Пробовал следующим образом: есть экземпляр класса с геттерами и сеттерами, в которых используется ReentrandReadWriteLock. Второй аналогичный класс использует Synchronized, третий - volatile-переменные. В цикле из 100 000 повторов провел три следующих тестирования: сперва из экземпляра одного из вышеуказанных классов читал в локальные переменные в потоке. Одновременно работают 50 потоков. Реализация полей с ReadLock от ReentrantReadWriteLock показала на чтении (и это без писателей!) в среднем 2700 миллисекунд на выполнение каждого потока (все 100000 повторов) Реализация с Synchronzed блока показала в среднем 850-970 миллисекунд Реализация с доступом к volatile-полям через геттеры - до 10 миллисекунд (что понятно). В этом тестовом проекте сделал возможность тестировать только на запись в синхронизируемые поля объекта. Те же 50 потоков, те же 100 000 циклов. Reentrant все так же проигрывает. Volatile-переменные начинают отнимать в среднем 80-100 миллисекунд, реализация с synchronized-блоками до 900 мс, ReentrantReadWriteLock - целых 2700 миллисекунд. По идее это ведь огромная конкуренция за ресурс, если я правильно понимаю, последний должен справляться с нею лучше в силу того, что не опускается до FAT-блокировок. Но Synchronized показал более высокие результаты. Наконец, тестирование, когда 50% - это чтение, а 50 - запись (случайным образом) - немного снизилось время, но в целом картина по каждой реализации та же. Теперь вопрос, почему? Если верить многочисленным источникам в интернете - ReentrantReadWriteLock "должен" был оказаться производительнее. Почему его блокировка как только на чтение, так и в других ситуациях отнимает больше всего времени? Есть у меня подозрение, что мне не хватает матчасти, какого-то базового понимания, как это работает. Благодарность не будет иметь предела за ссылки на официальные источники или подробные литературные источники о том, как это работает, когда ReentrantReadWriteLock показывает более положительные результаты, ну и вообще, за тыкание носом в очевидные вещи, которых я вероятно не знаю. :-) P.S.: Прошу прощения за большой объем текста. Если интересно, готов выложить тестовый проект. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2015, 19:44 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
Прошу прощения, в тесте только на чтение реализация с ReentrantReadWriteLock показала 2100 миллисекунд. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2015, 19:48 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
ReentrantReadWriteLock быстрее при условии высокой конкуренции за блокировку. synchronized будет быстрее при однопоточном выполнении и при низкой конкуренции. https://blogs.oracle.com/dave/entry/biased_locking_in_hotspot ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2015, 20:37 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, это тем более интересно, учитывая, что в тестовом проекте 50 потоков (много ли это?) борются за возможность обратиться к синхронизируемому ресурсу. Паузы между попытками захвата не стоит, возможно JVM как-то это оптимизирует? Но в целом: точно не один поток, субъективно - конкуренция "высокая". Или я не прав? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2015, 20:45 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, за ссылку отдельное спасибо! :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2015, 20:45 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
ДобрыйЧеловек, Производительность synchronized от версии к версии меняется. Возможно мои данные и устарели. Надо конечно же, анализировать сам тест, чтобы убедится что меряется именно производительность блокировки. Возможны, ведь и другие факторы на неё влияющие. ReentrantReadWriteLock не является полным аналогом synchronized, так как обеспечивает оптимизацию параллельного чтения разными потоками, чего с synchronized добиться, если и возможно, то сложнее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.07.2015, 10:26 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
Вот ещё пара ссылок mail list в котором можно найти массу интересного материала по теме http://cs.oswego.edu/mailman/listinfo/concurrency-interest Статья на столько старая, что Lock был быстрее. Есть смысл взять её примеры и прогнать на современной JRE. http://www.ibm.com/developerworks/java/library/j-jtp10264/ ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.07.2015, 10:30 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, ссылка на тестовый проект: https://yadi.sk/d/rnICwQ96hgsnw вдруг будет интересно поковырять Sleep только нужно убрать, он картину нормализует, чего нам в данном вопросе не нужно :-) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2015, 10:20 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
Спасибо еще раз за материалы, целая "клодовочка" :-) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2015, 10:23 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
ДобрыйЧеловекBlazkowicz, ссылка на тестовый проект: https://yadi.sk/d/rnICwQ96hgsnw вдруг будет интересно поковырять Sleep только нужно убрать, он картину нормализует, чего нам в данном вопросе не нужно :-) Перепишите тест правильно : берите org.openjdk.jmh Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. вопрос про 50 потоков - у вас есть реально 50 процессоров? Если нет то учитывается ли время на переключение ? если нет то тестируйте на не более чем 4 потоках , расскажите про результаты ? 3+1 потоках ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2015, 11:35 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
Волатилы неатомарны, кстати. Имейте в виду. Если вы пишите v = v+1 то это чтение, потом +1 и потом запись. И между чтением и записью другой поток легко может произвести свою запись - т.е. он в этом плане, точно так же как и с неволатилами. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2015, 12:20 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
chabapok, спасибо, да, об этом я уже почитал собственно говоря первое, что приходит в голову, когда знакомишься с volatile, что "а атомарен ли он"? :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2015, 15:31 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
Atum1, нет, один процессор, четыре ядра. Тест проводился на рабочей станции. По Вашей просьбе провел тестирование 3 + 1. Реализация Synchronized = 89 ms, ReentrantReadWriteLock = 150 ms. Еще, провел тестирование 50 потоков, не меняя проект (без Thread.sleep) в машине Java 1.7. Результаты существенно отличаются. С Synchronized в условиях, когда 20 чтений и 1 запись, примерно в 4-5 раз занимает больше времени. В случае с 3 + 1 разница еще существеннее, примерно в 7 раз. С org.openjdk.jmh был не знаком. Читаю мануал. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2015, 15:43 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
ДобрыйЧеловекAtum1, нет, один процессор, четыре ядра. Тест проводился на рабочей станции. По Вашей просьбе провел тестирование 3 + 1. Реализация Synchronized = 89 ms, ReentrantReadWriteLock = 150 ms. Еще, провел тестирование 50 потоков, не меняя проект (без Thread.sleep) в машине Java 1.7. Результаты существенно отличаются. С Synchronized в условиях, когда 20 чтений и 1 запись, примерно в 4-5 раз занимает больше времени. В случае с 3 + 1 разница еще существеннее, примерно в 7 раз. С org.openjdk.jmh был не знаком. Читаю мануал. Напишите тест на основе org.openjdk.jmh и покажите результаты :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2015, 17:31 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
17702411 как пример использования org.openjdk.jmh ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2015, 17:33 |
|
||
|
ReentrantReadWriteLock медленнее Synchronized?
|
|||
|---|---|---|---|
|
#18+
Atum1 17702411 как пример использования org.openjdk.jmh Да и эталонную реализацию, не забудьте - только чтение - без записи - static final singleton какое будет время ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2015, 17:38 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=39003309&tid=2125187]: |
0ms |
get settings: |
7ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
85ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
35ms |
get tp. blocked users: |
1ms |
| others: | 244ms |
| total: | 402ms |

| 0 / 0 |
