Почему несинхронизация делает ArrayList быстрее и менее безопасным? - PullRequest
4 голосов
/ 19 мая 2011

Я прочитал следующее утверждение:

ArrayLists не синхронизированы и, следовательно, быстрее, чем Vector, но менее безопасны в многопоточной среде.

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

Ответы [ 6 ]

10 голосов
/ 19 мая 2011

Я постараюсь ответить на оба ваших вопроса:

Улучшение скорости

Если бы ArrayList были синхронизированы и несколько потоков пытались прочитать данные изв то же время, потоки должны были бы ждать, чтобы получить эксклюзивную блокировку в списке.Оставляя список несинхронизированным, потокам не нужно ждать, и программа будет работать быстрее.

Небезопасно

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

2 голосов
/ 19 мая 2011

ArrayLists не синхронизированы и, следовательно, быстрее, чем Vector, но менее безопасны в многопоточной среде.

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

Когда несколько потоков читают / записывают в общую память, программа может вычислить неверные результаты из-за отсутствия взаимного исключения и надлежащей видимости.Следовательно, отсутствие синхронизации считается «небезопасным». Это сообщение в блоге Джереми Мэнсона может послужить хорошим введением в тему.

Когда JVM выполняет синхронизированный метод, он гарантирует, что текущий поток имеет монопольную блокировку объекта накакой метод вызывается.Точно так же, когда метод заканчивает выполнение, JVM освобождает блокировку, удерживаемую исполняющим потоком.Синхронизированные методы обеспечивают взаимное исключение и гарантии видимости - и это важно для «безопасности» (т. Е. Обеспечения правильности) исполняемого кода.Но, если только один поток когда-либо обращается к методам объекта, нет проблем с безопасностью.Несмотря на то, что производительность JVM улучшилась за прошедшие годы, бесконтрольная синхронизация (т.е. блокировка / разблокировка объектов, к которым обращается только один поток), все же занимает ненулевое количество времени.Для несинхронизированных методов JVM не платит этот дополнительный штраф - следовательно, они быстрее, чем их синхронизированные аналоги.

Vector s навязывают вам свой выбор.Все методы synchronized, и их сложно использовать неправильно.Но когда Vector s используются в однопоточном контексте, вы платите цену за дополнительную синхронизацию без необходимости.ArrayList ы оставляете за вами выбор.При использовании в многопоточном контексте, вы (программист) должны правильно синхронизировать код;но при использовании в однопоточном контексте вы гарантированно не будете платить лишние затраты на синхронизацию.

Кроме того, при первоначальном заполнении коллекции и последующем чтении ArrayList работают лучше даже в многопоточном контексте.Например, рассмотрим этот метод:

public synchronized List<String> getList() {
    List<String> list = new Vector<String>();
    list.add("Foo");
    list.add("Bar");
    return Collections.unmodifiableList(list);
}

Список создается, заполняется, и его неизменное представление безопасно публикуется.Глядя на приведенный выше код, становится ясно, что все последующие использования этого списка считываются и не требуют какой-либо синхронизации, даже если используются несколькими потоками - объект является эффективно неизменным .Использование Vector здесь приводит к накладным расходам синхронизации даже для операций чтения, где это не требуется;вместо этого лучше использовать ArrayList.

2 голосов
/ 19 мая 2011

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

0 голосов
/ 19 мая 2011
Потоки

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

http://download.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html
Прочтите «Обратите внимание, чтоэта реализация не синхронизирована. "параграф, это объясняет немного лучше.

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

0 голосов
/ 19 мая 2011

Структуры данных, которые синхронизируют, используют блокировки (или другие конструкции синхронизации), чтобы гарантировать, что их данные всегда находятся в согласованном состоянии. Часто для этого требуется, чтобы один или несколько потоков ожидали в другом потоке, чтобы завершить обновление состояния структуры, что снизит производительность, поскольку ожидание было введено там, где раньше его не было.

0 голосов
/ 19 мая 2011

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

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

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