- 1
- 2
- 3
synchronized(new Object()){
...
}
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+100
synchronized(new Object()){
...
}
http://stackoverflow.com/questions/9840959/how-to-judge-which-object-to-be-synchronized-in-java-thread
Писал как-то раз такую синхронизацию в жабе. Сознательно писал.
Ибо нужно было дублировать 2 куска кода - один для несинхронизированных инстансов (завернутый в synchronized), другой для синхронизированных (никуда не завернутый).
Вот так:
>Collections.synchronizedMap()
Кстати это мысль. Но только заворачивать в него несинхронизированные.
Но как пример подход где можно использовать new Object(), вполне ведь легитимно?
Вот-вот. Это позволит ускорить код, ведь не будет медленного захвата монитора для никому не нужного обжекта.
new Object() можно, можно ещё Lock явно заюзать. Кода больше, но намерения более явные, и можно добиться условной блокировки.
Кстати, если блок состоит из нескольких операций над мапой, для конкурентных мап появлятся race condition.
Там в некоторых других местах нужен именно atomic, потому тупо лок на мапе и проверка уже на ConcurrentMap.
> не будет медленного захвата монитора для никому не нужного обжекта.
Лажа в том что для synchronizedMap() тоже создается ненужный объект - обертка. Для GC однохуйственно.
Но теперь на любом вызове метода get, put, contains будет происходть "медленный захват монитора".
Ведь внутри synchronizedMap() те же секции synchronized.
Если нужно сымитировать именно базовые операции из ConcurrentMap для обычных, я бы обошёлся обёрткой, делающий из обычной мапы ConcurrentMap с внутренней синхронизацией.
Если нужны более сложные операции, то для конкурентных коллекций всё равно потребуется синхронизация, ибо создаёт race condition, хоть и не сломает саму мапу (как может приключиться с обычной мапой).
> потому тупо лок на мапе и проверка уже на ConcurrentMap
Я об этом и написал. Проверка на ConcurrentMap, каст в неё и вызов того же putIfAbsent.
Просто говорю, что
а) от медленного захвата монитора никуда не уйти
б) в случае когда нет готовой синхронизированной обертки, а писать её лень лок по new Object() - самый простой и эффективный подход. По GC выигрыша нет. И там, и там создается объект.
>вот что не совсем понятно: если нужна атомарная операция
Она нужна в другом куске кода.
Если конкурентная мапа, не лочим временных объектов, да и логика прозрачней.
>>Проверка на ConcurrentMap, каст в неё и вызов того же putIfAbsent.
Но это в другом месте, где нужна неделимость операций.
Это, по-моему, единственный здравый способ. Как-то по-другому написать это трудно.
synchronizedMap() позволит лишь избежать лишнего захвата монитора для конкурентных мап, но привнесёт несколько захватов для неконкурентных. К тому же, его нельзя использовать, если мапа доступна извне, что скорее всего верно.
А в целом это увиливание от жавопроблем - в т.ч. плохого метода synchronizedMap, который тупо заворачивает всё. В этом плане чистые языки думаю избавят нас от лютого многопоточного майндфака.
Только внутри sync-mapa