Лучший Java-потокобезопасный механизм блокировки для коллекций? - PullRequest
4 голосов
/ 15 января 2011

Каким был бы наименее медленный потокобезопасный механизм для управления множественным доступом к коллекции в Java?

Я добавляю объекты в начало коллекции, и я очень не уверен, что будет лучшимвыполняя коллекцию.Будет ли это вектор или очередь?Первоначально я думал, что ArrayList будет быстрым, но я провел несколько экспериментов, и он был очень медленным.

РЕДАКТИРОВАТЬ: В моем тесте вставки вектор, задержанный с использованием volatile, кажется самым быстрым?

Ответы [ 6 ]

6 голосов
/ 15 января 2011

Посмотреть коллекции в java.util.concurrent.

5 голосов
/ 15 января 2011

Лучшие алгоритмы максимально избегают общего состояния. Похоже, вы новичок в многопоточном программировании в Java. Почему бы просто не выбрать что-то, что, как вы знаете, будет правильным ... Затем посмотрите, сколько существует синхронизации, затем посмотрите, не является ли это проблемой ..., а затем посмотрите, сможете ли вы найти более быстрый способ сделать это.

4 голосов
/ 15 января 2011

Точные используемые операции должны определять, что используется.Однако, поскольку контейнер является в значительной степени абстрактным типом, напишите его так, чтобы он работал - надежно - затем профилируйте, обеспечьте функциональные требования, оптимизируйте по мере необходимости, бла-бла:)

Обычно,мое основное использование для "параллельной коллекции" - это очередь, которая используется для передачи объектов между потоками.В этом случае я начинаю с ConcurrentLinkedQueue , если не по какой-либо другой причине, кроме симпатии к алгоритму «без блокировки» (это не значит, что он будет быстрее: -).

ОбычноОчередь и / или LinkedList - это хорошая структура данных, которую нужно добавить в конец.В зависимости от обстоятельств, включая конкретные шаблоны использования, включая: конфликт потоков, количество удаленных элементов, порядок удаления элементов и т. Д. , «быстрое уничтожение» всего, кроме начала / конца может Быстрее выполнить с помощью clear (часть AbstractQueue) и повторного добавления предметов - ConcurrentLinkedQueue позволяет осматривать / манипулировать хвостом и головы.Тем не менее, я хотел бы призвать «держать его проще», писать в «конкретный контракт интерфейса» и «просто использовать текущий подход», пока не будет убедительных доказательств того, что функциональное требование не выполнено.

Что касаетсяпроизводительность, это действительно зависит от конкретных характеристик структуры данных сценария использования / операций и реализации структуры данных.В некоторых случаях ArrayList может быть очень медленным, чем Vector, и это действительно задокументировано.Если это представление имеет значение, хотя, что-то звучит подозрительно.Статья на Java Best Practices - Vector против ArrayList против HashSet содержит хорошее чтение.Обратите также внимание на комментарии.

Edit: Помните, что "параллельная" структура данных обычно подразумевает только то, что одиночная операция (вызов метода) является атомарной(и, возможно, не все операции в нечетных случаях!).Для достижения требуемого уровня безопасности потока все еще может потребоваться реализовать синхронизацию с большой областью действия или другой подход.Таким образом, h.putIfAbsent(k,v) (из ConcurrentHashMap) - это не то же самое , что и if (!h.containsKey(k)) { h.put(k, v); } - как пример, проблема, подобная этой, относится к упомянутому подходу «очистить, а затем добавить»выше.

Счастливого кодирования.

0 голосов
/ 15 января 2011

ConcurrentSkipListMap / Set - но вы должны знать, как / КОГДА его использовать. CopyOnWriteArrayList - еще одно замечательное решение (опять же нужно знать, почему вы его используете).

РЕДАКТИРОВАТЬ: В моем тесте вставки вектор, задержанный с использованием volatile, кажется самым быстрым?

Это просто не круто и совершенно бесполезно.

0 голосов
/ 15 января 2011

Э-э, если я правильно понимаю комментарий "Vector using volatile", вы можете не совсем понять, что означает синхронизация.Volatile будет применяться только для ссылки на Vector;и поскольку сам вектор синхронизирован, он будет избыточным.

Но, по сути, действительно ли вы считаете, что различия в производительности из-за синхронизации (для доступа к контейнеру) имеют значение для вас, чтобы беспокоиться?Если вы это сделаете, вы сможете увидеть эффект с помощью профилирования (горячие точки в доступе и / или мутации).Я не говорю, что не бывает случаев, когда это может произойти, но они не особенно распространены.

0 голосов
/ 15 января 2011

Возможно, написать свою собственную реализацию LinkedList?

В коллекции java хранится только текущий указатель. Вы можете иметь тот, который держит голову и хвост ...

Вы также можете обернуть его внутри Collections.synchronizedList (...)

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