2010-05-21 5 views
32

Вектор синхронизирован, ArrayList не синхронизирован, но мы можем синхронизировать ArrayList на Collections.synchronizedList(aList), так что будет работать лучше и быстрее?Vector vs Collections.synchronizedList (ArrayList)

+1

Если это C#, пожалуйста, пометьте свой вопрос «C#» или «.NET». – FrustratedWithFormsDesigner

+1

Почему бы вам не написать тест и не узнать? – skaffman

+0

Можете ли вы объяснить шаблон использования? 1) Многие записи/многие читают 2) Мало пишет, многие читают, 3) Многие пишут, мало читает 4) Немного/немного не нуждается в оптимизации – TJR

ответ

4

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

int i = 0; 
while (i < list.size()) 
{ 
    if (testSomeCondition(list.get())) { 
    list.remove(i); 
    else 
    i++; 
} 

Наш список может быть синхронизирована (например, вектор) и этот код будет по-прежнему сломать ужасно. Зачем? Поскольку индивидуальные вызовы size(), get(), remove(), синхронизируются, но один поток все равно может удалять элементы из списка, а другой - итерации по нему. Другими словами, у нас есть условие гонки, и использование синхронизированных коллекций ничего нам не принесло.

Чтобы исправить гонку, мы должны синхронизировать всю операцию с коллекцией или использовать параллельные блокировки Java 5, чтобы сделать то же самое.

synchronized (list) { 
    int i = 0; 
    while (i < list.size()) 
    { 
    if (testSomeCondition(list.get())) { 
     list.remove(i); 
    else 
     i++; 
    } 
} 

Этот блок кода теперь является потокобезопасным, поскольку только один поток может выполнять цикл за раз. И теперь нет причин использовать синхронизированную коллекцию. Мы можем использовать ArrayList вместо Vector и сэкономить себе штраф за выполнение всех этих синхронизированных вызовов.

Поэтому не используйте синхронизированные коллекции. Если вы обнаружите, что несколько потоков попадают в один и тот же список, вам необходимо защитить операции в списке, а не отдельные вызовы.

+9

«Синхронизированные коллекции - пустая трата времени». - слишком общий. Цели, связанные с синхронизацией. Вы просто приводите пример того, как использовать их неправильно. Соломенный аргумент. – thejoshwolfe

+0

Они являются пустой тратой времени буквально. Синхронизированное ключевое слово налагает штраф за вызов, даже если коллекция используется исключительно одним потоком. И большинство коллекций будут использоваться исключительно одним потоком. И даже если они разделены, синхронизация индивидуального вызова по-прежнему позволяет использовать условия гонки, поэтому они не подходят для цели. Разработчик просто тратит свое время на поиск ошибок в своих якобы потокобезопасных коллекциях. Проще говоря, эти коллекции токсичны и никогда не должны использоваться, кроме случаев, когда их не избежать (например, устаревшие случаи, J2ME и т. Д.). – locka

+1

Синхронизация была медленной в java 1.3 и ранее. В современной java это лучше. http://www.ibm.com/developerworks/java/library/j-jtp04223/index.html Кроме того, опять же с соломенными соображениями. Никто не использует синхронизацию с ситуацией, которая, как известно, является однопоточной. Ваш первый пример - просто плохое программирование, и никакая коллекция никогда не сможет это компенсировать. Вы просто должны думать о том, что является или не является атомом, независимо от того, какую коллекцию вы используете. Взгляните на код remove() в ArrayList, и вы поймете, почему этот метод необходимо синхронизировать для поддержания целостности списка. – Gus