Синхронное внедрение бизнес-логики - PullRequest
2 голосов
/ 05 февраля 2011

Реализация с использованием существующих классов синхронизированной Java (Hashtable, StringBuffer, Vector)

или

синхронизация блоков при реализации несинхронизированных классов Java (HashMap,StringBuilder, ArrayList)

или

создать синхронизированные объекты коллекции из метода Collections.synchronizedXXX () и затем использовать его (конечно, я не могу синхронизировать StringBuilderвот так. !!)

В многопоточном сценарии, какой из вышеперечисленных будет лучшим способом для синхронизации без какого-либо снижения производительности?

Заранее спасибо. !!!

1 Ответ

2 голосов
/ 05 февраля 2011

Лучший подход зависит от того, что именно ваш код пытается сделать, и от уровня атомарности, который вам требуется. Иногда Collections.synchronizedWhatever в порядке; иногда вам нужно выполнить собственную синхронизацию.

С точки зрения производительности вам просто нужно убедиться, что вы минимизируете количество вводимых блоков synchronized. Там будет небольшая разница между

(example A)
List l = Collections.synchronizedList(originalList);
l.add(something);

и

(example B)
synchronized (originalList) {
    originalList.add(something);
}

потому что они оба входят в один синхронизированный блок. Однако:

(example C)
List l = Collections.synchronizedList(originalList);
l.add(something);
int index = l.indexOf(something);

введет два синхронизированных блока, тогда как

(example D)
synchronized (originalList) {
    originalList.add(something);
    int index = originalList.indexOf(something);
}

войдет только в один синхронизированный блок. Конечно, он тратит больше времени в этом блоке, так что это может увеличить конкуренцию, но add и indexOf теперь ведут себя как одна атомарная операция. Это может или не может быть тем, что вы хотите: это полностью зависит от приложения.

РЕДАКТИРОВАТЬ: Чтобы ответить на вопрос Дипака:

'synchronizedList' в примере C означает, что каждый вызов метода в 'l' будет заключен в синхронизированный блок. Вы можете думать о C как об этом:

synchronized (originalList) {
    originalList.add(something);
}
synchronized (originalList) {
    int index = originalList.indexOf(something);
}

Здесь есть некоторая дополнительная стоимость, но, если она не находится в критической части вашего кода, это, вероятно, не будет проблемой. Я бы посоветовал вам больше задуматься о том, чтобы убедиться, что ваш код ведет себя правильно, прежде чем подумать об его оптимизации. Трудно сделать правильный потокобезопасный код, поэтому будьте очень осторожны с тем, как вы пишете вещи. Например, в C существует возможное состояние гонки между «l.add (что-то)» и «l.indexOf (что-то)». У D нет одинакового состояния гонки, потому что обе операции находятся внутри одного синхронизированного блока.

Книга Брайана Гетца (Java Concurrency in Practice) является отличным ресурсом для обучения написанию поточно-ориентированного кода. Я очень рекомендую это. Я уверен, что это на Амазоне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...