У нас есть несколько вызовов потоков add(obj)
на ArrayList
.
Моя теория - это когда add
назван одновременно двумя потоками, это, только один из двух добавляемых объектов действительно добавляется к ArrayList
. Действительно ли это вероятно?
Если так, как Вы обходите это? Используйте синхронизируемый набор как Vector
?
Не существует гарантированного поведения того, что происходит, когда добавление вызывается одновременно двумя потоками в ArrayList. Однако, по моему опыту, оба объекта были добавлены нормально. Большинство проблем безопасности потоков, связанных со списками, связаны с итерацией при добавлении / удалении. Несмотря на это, я настоятельно рекомендую не использовать ванильный ArrayList с несколькими потоками и одновременным доступом.
Вектор раньше был стандартом для параллельных списков, но теперь стандартом является использование синхронизированного списка Коллекции .
Также я настоятельно рекомендую Java Concurrency in Practice от Goetz et al, если вы собираетесь тратить какое-то время на работу с потоками в Java. В книге этот вопрос освещен гораздо лучше.
Вы также можете получить null
, ArrayOutOfBoundsException
или что-то еще, оставшееся до реализации. HashMap
уходит в бесконечный цикл в производственных системах. Вам действительно не нужно знать, что может пойти не так, просто не делайте этого.
Вы можете использовать Vector
, но это, как правило, приводит к тому, что интерфейс недостаточно богат. Вы, вероятно, обнаружите, что в большинстве случаев вам нужна другая структура данных.
вы можете использовать List l = Collections.synchronizedList (new ArrayList ());
, если вам нужна поточно-безопасная версия arrayList.
http://java.sun.com/j2se/1.4.2/docs/api/java/util/ArrayList.html
Обратите внимание, что эта реализация не синхронизирована. Если несколько потоков обращаются к экземпляру ArrayList одновременно, и хотя бы один из потоков структурно изменяет список, он должен быть синхронизирован извне.
Поскольку внутренней синхронизации нет, то, что вы теоретизируете, неправдоподобно.
Таким образом, ситуация выходит из строя, что приводит к неприятным и непредсказуемым результатам.
java.util.concurrent имеет список потоковобезопасных массивов. Стандартный список ArrayList не является потокобезопасным, и поведение при одновременном обновлении нескольких потоков не определено. Также может быть странное поведение с несколькими читателями, когда один или несколько потоков пишут одновременно.
Произойдет любое количество вещей. Вы можете правильно добавить оба объекта. Вы могли добавить только один из объектов. Вы можете получить исключение ArrayIndexOutOfBounds, потому что размер базового массива не был скорректирован должным образом. Или могут произойти другие вещи. Достаточно сказать, что вы не можете полагаться на какое-либо поведение.
В качестве альтернативы вы можете использовать Vector
, вы можете использовать Collections.synchronizedList
, вы можете использовать CopyOnWriteArrayList
или использовать отдельную блокировку. Все зависит от того, что еще вы делаете и какой у вас контроль над доступом к коллекции.
Поведение, вероятно, не определено, поскольку ArrayList не является потокобезопасным. Если вы измените список, когда Iterator взаимодействует с ним, вы получите ConcurrentModificationException. Вы можете обернуть ArrayList с помощью Collection.synchronizedList или использовать потокобезопасную коллекцию (их много) или просто поместить вызовы добавления в синхронизированный блок.