|
|
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
Кто подскажет шаблон для синхронизации кода не по экземпляру объекта, а по строке? То есть чтобы одновременные вызовы someMethod("a") и someMethod("b") выполнялись параллельно, а вызовы someMethod("a") и someMethod("a") - по очереди. Я придумал такой код, но есть подозрения в том, что он неоптимален: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 18:13:18 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
А чего вы хотите добиться? Я имею ввиду, что возможно вы идете окружным путем, а решение проще и элегантней. Что касается того кода что вы привели, выполнить какой-то код, основываясь на параметре, то да, можно завести коллекцию, не обязательно ConcurrentHashMap, в цикле делать CAS, ожидая пока ячейка освободиться, и когда освободиться выполнить свой код, Только опять же иногда CAS намного хуже чем обычный Lock, если contention большой. Можете описать задачу конкретней? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 18:38:15 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
Я так полагаю что это какое-то подобие кэша, который поддерживает работу с несколькими потоками? Тогда вам определенно надо скачать Java Concurrency in practice, там целая глава посвящена кэшам, и есть там хороший пример с Future и Computable ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 18:40:54 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
забыл ник, Это не подобие хэша. Я пишу обработчик вызовов удаленного метода. У меня есть некая сущность, скажем, клиентский счет. Он идентифицируется строковым UUID'ом. Таких сущностей на сервере может быть несколько тысяч. Мне надо делать синхронизацию на основе UUID'а. Чтобы два клиента одновременно не редактировали одновременно эту сущность. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 19:12:09 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
Во-первых, я не очень понимаю, зачем нужна проверка на null. Во-вторых, что из себя представляет эта сущность? Если это объект внутри JVM, то синхронизируйтесь прям на нем. Если это строчка в базе данных, то захватывайте лок на этой строчке в БД (это происходит автоматически при update или delete). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 19:26:39 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
авторВо-вторых, что из себя представляет эта сущность? Если это объект внутри JVM, то синхронизируйтесь прям на нем. Если это строчка в базе данных, то захватывайте лок на этой строчке в БД (это происходит автоматически при update или delete). Я тоже так думаю, может топикстартер чего-то недоговаривает? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 19:30:52 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
Йуный джавистЪВо-первых, я не очень понимаю, зачем нужна проверка на null. Почитайте джавадок метода ConcurrentMap.putIfAbsent() Йуный джавистЪВо-вторых, что из себя представляет эта сущность? Если это объект внутри JVM, то синхронизируйтесь прям на нем. Спасибо, кэп! :) Йуный джавистЪЕсли это строчка в базе данных, то захватывайте лок на этой строчке в БД (это происходит автоматически при update или delete). Это сущность в нереляционном дата-бэкенде. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 19:32:58 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
забыл никавторВо-вторых, что из себя представляет эта сущность? Если это объект внутри JVM, то синхронизируйтесь прям на нем. Если это строчка в базе данных, то захватывайте лок на этой строчке в БД (это происходит автоматически при update или delete). Я тоже так думаю, может топикстартер чего-то недоговаривает? Это сущность в самописном нереляционном дата-бэкенде. У меня нет уверенности в корректной поддержке конкурентной модификации сущностей внутри этого бэкенда. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 19:41:35 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
Почитайте джавадок метода ConcurrentMap.putIfAbsent() Теперь понял. Это сущность в нереляционном дата-бэкенде. Можно поинтересоваться, в каком? Даже в файловой системе есть локи. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 19:41:49 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
Это сущность в нереляционном дата-бэкенде. Можно поинтересоваться, в каком? Даже в файловой системе есть локи. Кэширующее реплицируемое хранилище игровых объектов. По сути легаси-система, написана на С++. Используется в многопользовательской игре. Количество типов объектов ограничено и заранее описано. Не знаю, что ещё рассказать Вам о нем. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 19:50:14 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
shainsky, Кладите вместо строки либо просто новый созданный объект, либо какую-нибудь из реализаций java.util.concurrent.locks.Lock ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 20:02:49 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
schwashainsky, Кладите вместо строки либо просто новый созданный объект, либо какую-нибудь из реализаций java.util.concurrent.locks.Lock Вместо current = s написать current = new Object() ? А в чем здесь оптимизация? В моем случае кладется уже существующий объект, а в Вашем - новый, который надо создавать и хранить. Или я неправильно понял? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 20:11:14 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
Вы не то оптимизируете - вам нужно оптимизировать время пребывания в блоке synchronized и количество тех, кто борется за это монитор. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 20:28:34 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
За этоТ монитор, который создается, или достается из мапа, а вы боритесь с GC вместо этого. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 20:30:18 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
intern() но это не очень здорово, поэтому проще создать Код: java 1. 2. 3. 4. 5. 6. и синхронизироваться по нему ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2012, 23:40:58 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
shainsky, Еще вариант Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 00:02:28 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
OOsalivanshainsky, Еще вариант Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Зачем эта мутотень если уже 5 лет есть Lock? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 02:15:51 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
забыл никЗачем эта мутотень если уже 5 лет есть Lock? Lock есть, и как вы его собираетесь к этой задаче применить, где ваш код? Или это самоутверждение? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 10:23:27 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
schwaВы не то оптимизируете - вам нужно оптимизировать время пребывания в блоке synchronized и количество тех, кто борется за это монитор. +1 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 10:29:14 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
OOsalivanshainsky, Еще вариант Код: java 1. 2. 3. 4. 5. Как на счет spurious wakeup? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 10:29:47 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
OOsalivanLock есть, и как вы его собираетесь к этой задаче применить, где ваш код? Или это самоутверждение? Всё тоже самое, только вместо Object - Lock и synchronized не нужен. Lock рекомедуют к использованию вместо wait/notify. Но мне любопытно на счет производительности. Lock устроен горзда сложнее с кучей вызовов методов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 10:33:17 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
BlazkowiczOOsalivanshainsky, Еще вариант Код: java 1. 2. 3. 4. 5. Как на счет spurious wakeup? А где вы видите проблему с spurious wakeup? while (map.put(s, true) == true) - как раз для этого и написано ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 12:13:19 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
OOsalivanА где вы видите проблему с spurious wakeup? while (map.put(s, true) == true) - как раз для этого и написано Ааа, там предыдущее значение выталкивается. Я подумал что флаг. А NPE не будет ли при анбоксинге null? В любом случае при первом заходе там всегда не true. Рантайм в цикл вообще не попадёт. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 12:24:20 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
BlazkowiczАаа, там предыдущее значение выталкивается. Я подумал что флаг. А NPE не будет ли при анбоксинге null? В любом случае при первом заходе там всегда не true. Рантайм в цикл вообще не попадёт. Ой, блин что-то я гоню. Это же только для того случая если строка есть. А ещё вопрос, все ведь строки на одном локе висят. Тогда если две разных строки в 2х потоках уже существуею, они ещё и с друг другом будут бодаться за lock? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 12:26:08 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
И ещё вопрос к коду. Как отработает re-entrancy, если метод вызовется для той же строки, но в том же потоке? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 12:28:27 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
А ещё, расскажи, если не трудно, для чего true/false. Не проще ли через Set и проверку на null? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 12:29:55 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
BlazkowiczBlazkowiczАаа, там предыдущее значение выталкивается. Я подумал что флаг. А NPE не будет ли при анбоксинге null? В любом случае при первом заходе там всегда не true. Рантайм в цикл вообще не попадёт. Ой, блин что-то я гоню. Это же только для того случая если строка есть. А ещё вопрос, все ведь строки на одном локе висят. Тогда если две разных строки в 2х потоках уже существуею, они ещё и с друг другом будут бодаться за lock? Когда поток переходит в состояние wait он освобождает монитор объекта. Поэтому все строки которые соответствуют map.put(s, true) == true - т.е предыдущее значение для данного ключа(строки) == true - будут переходить в состояние wait. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 12:59:15 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
BlazkowiczИ ещё вопрос к коду. Как отработает re-entrancy, если метод вызовется для той же строки, но в том же потоке? Когда поток вызывает lock.notifyAll(); он переводит все потоки(которые висят на данном локе) в активное состояние. Если у нас есть стек потоков с одним ключом (s) которые на момент lock.notifyAll() висели на нашем локе - то первый из них выигрывает ресурс map.put(s, true) == false и работает с критической областью, а остальные по условию map.put(s, true) == true переходят в состояние wait. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 13:06:50 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
notifyAll() тоже ведь завернуть нужно в synchronized ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 13:10:59 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
OOsalivanКогда поток вызывает lock.notifyAll(); он переводит все потоки(которые висят на данном локе) в активное состояние. Если у нас есть стек потоков с одним ключом (s) которые на момент lock.notifyAll() висели на нашем локе - то первый из них выигрывает ресурс map.put(s, true) == false и работает с критической областью, а остальные по условию map.put(s, true) == true переходят в состояние wait. Нее, re-entrancy, это про один поток. Если вдруг поток вызовет метод, положит строку и потом в какой-то момент снова вызовет этот же метод. Он же залочится до тех пор пока кто-то по другой строке его не разбудит. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 13:13:33 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
BlazkowiczА ещё, расскажи, если не трудно, для чего true/false. Не проще ли через Set и проверку на null? Можно и через Set - только какую имплиминтацию брать? Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 13:42:23 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
OOsalivanМожно и через Set - только какую имплиминтацию брать? Collections.newSetFromMap() ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 13:47:32 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
BlazkowiczLock рекомедуют к использованию вместо wait/notify. Но мне любопытно на счет производительности. Lock устроен горзда сложнее с кучей вызовов методов. Насчет производительности - многое зависит от имплементации JVM, но если брать HotSpot, то рекомендуют использовать synchronized в случае если с кодом работает в основном один поток, причем если синхронизация происходит все время по одному объекту(так как возможно применить так называемый biased locking), в данном случае это не наблюдается. Вариант когда с кодом работает один поток, но синхронизация по разным объектам и количество "столкновений на мониторе" невысоко, то оба подхода дают примерно одинаковый результат, так как оба работают на CASе, а вот выигрывать Lock начинает при большом столкновении, так как synch сразу раздувается до OS-level монитора, а Lock имплементирован так, что может адаптивно подстраиваится, и перейти на OS-level и обратно при определенных условиях. Все это более подробно описывается тут - http://www.javaspecialist.ru/2011/11/synchronized-vs-reentrantlock.html#more BlazkowiczА ещё вопрос, все ведь строки на одном локе висят. Тогда если две разных строки в 2х потоках уже существуею, они ещё и с друг другом будут бодаться за lock? И ещё вопрос к коду. Как отработает re-entrancy, если метод вызовется для той же строки, но в том же потоке? Вот именно поэтому я и говорю, что надо использовать ReentrantLock, причем он должен быть не глобальным, а содержаться в Map Код: java 1. и лочить надо именно не глобальный лок, а тот что доступен по ключу-строке, тогда столкновений на разных строках на одном мониторе не будет, что значительно увеличит производительность, как вы и заметили. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 14:23:26 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
BlazkowiczНее, re-entrancy, это про один поток. Если вдруг поток вызовет метод, положит строку и потом в какой-то момент снова вызовет этот же метод. Он же залочится до тех пор пока кто-то по другой строке его не разбудит. Ну а в случае с обычной синхронизацией (через синхронайз) что произойдет? Это по моему общая проблема ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 14:31:34 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
забыл никBlazkowiczА ещё вопрос, все ведь строки на одном локе висят. Тогда если две разных строки в 2х потоках уже существуею, они ещё и с друг другом будут бодаться за lock? И ещё вопрос к коду. Как отработает re-entrancy, если метод вызовется для той же строки, но в том же потоке? Вот именно поэтому я и говорю, что надо использовать ReentrantLock, причем он должен быть не глобальным, а содержаться в Map Так какую проблему решает ReentrantLock по отношению к Object.wait ? Object.wait просто переводит поток в состояние ожидания, и из- за того что этот метод релизит монитор после перевода, то может использоваться сколько угодно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 14:45:44 |
|
||
|
Синхронизация по String
|
|||
|---|---|---|---|
|
#18+
shainsky Я придумал такой код, но есть подозрения в том, что он неоптимален: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. Строка workWith.remove(s); лишняя, в случае, если потоков будет больше двух и они параллельно будут вызывать этот метод, то есть вероятность, что второй и третий потоки зайдут одновременно в синхронизированный блок. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2012, 18:43:44 |
|
||
|
|

start [/forum/topic.php?all=1&fid=59&tid=2132140]: |
0ms |
get settings: |
12ms |
get forum list: |
27ms |
check forum access: |
6ms |
check topic access: |
6ms |
track hit: |
51ms |
get topic data: |
18ms |
get forum data: |
6ms |
get page messages: |
95ms |
get tp. blocked users: |
2ms |
| others: | 407ms |
| total: | 630ms |

| 0 / 0 |
