2016-09-22 3 views
1

Я хотел бы знать, каковы ВЛИЯНИЕ ВОЗМОЖНО последствия (помимо повреждения данных) несинхронизации коллекции, которая модифицируется несколькими потоками в Java.Последствия несинхронизирующих коллекций Java

Реальный пример: количество потоков может быть больше 10, а коллекция (HashSet) может вырасти примерно до 100 000 элементов (и, возможно, даже больше).

Благодаря

+0

В результате вы получите поврежденные данные и не сможете получить доверие. – TheLostMind

+1

Что касается 'HashMap', вы можете получить мертвую петлю. – passion

+0

@passion вы могли бы объяснить немного больше. Это что-то вроде бесконечного цикла? – filip

ответ

2

Поскольку HashSet использует HashMap внутри, вы можете просто посмотреть в putVal определение метод HashMap и посмотреть на себя - в любой момент выполнения этого метода, другой поток может начать делать то же самое. Он может, например, перехватить его средним размером, что означает, что данные могут быть записаны в старую таблицу или две новые таблицы будут созданы одновременно.

Результатом всегда является повреждение данных, возможно, это не сработает после такого инцидента.

1

Вы можете получить ConcurrentModificationException, если один из потоков выполняет итерацию по набору, а другой поток изменяет его.

Подробное объяснение в документации HashSet:

Обратите внимание, что эта реализация не синхронизируется. Если несколько потоков обращаются к хеш-набору одновременно, и по крайней мере один из потоков изменяет набор, он должен быть синхронизирован извне. Обычно это выполняется путем синхронизации на некотором объекте, который, естественно, инкапсулирует набор. Если такой объект не существует, набор должен быть «завернут» с использованием метода Collections.synchronizedSet. Лучше всего это сделать во время создания, чтобы предотвратить случайный несинхронизированный доступ к набору:

Set s = Collections.synchronizedSet(new HashSet(...));

Итераторы возвращаемого метод итератора этого класса является отказоустойчивость быстро: если набор изменен в любое время после того, как итератор создается любым способом, кроме как через собственный метод удаления итератора, Iterator выбрасывает ConcurrentModificationException. Таким образом, перед лицом одновременной модификации итератор быстро и чисто, а не рискует произвольным, недетерминированным поведением в неопределенное время в будущем.

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

1

Наихудшее из того, что ваша структура данных заканчивается, указывает на себя, например. HashMap до Java 7 может попасть в бесконечный цикл. Таким образом, вы не получаете никакой ошибки, а ваш поток никогда не возвращается.