В Java, нужно ли объявлять мою коллекцию синхронизированной, если она доступна только для чтения?
Я заполняю коллекцию один раз, когда запускается мой веб-приложение J2EE.
Затем несколько потоков могут получить к нему доступ в одно и то же время, но только для чтения.
Я знаю, что использование синхронизированной коллекции является обязательным для написания параллелей, но мне все еще нужно это для чтения параллелей?
Ответы
Ответ 1
Обычно нет, потому что вы не меняете внутреннее состояние коллекции в этом случае. Когда вы перебираете коллекцию, создается новый экземпляр итератора, а состояние итерации - для экземпляра итератора.
Примечание: Помните, что, сохраняя коллекцию только для чтения, вы предотвращаете модификации самой коллекции. Каждый элемент коллекции по-прежнему изменчив.
class Test {
public Test(final int a, final int b) {
this.a = a;
this.b = b;
}
public int a;
public int b;
}
public class Main {
public static void main(String[] args) throws Exception {
List<Test> values = new ArrayList<Test>(2);
values.add(new Test(1, 2));
values.add(new Test(3, 4));
List<Test> readOnly = Collections.unmodifiableList(values);
for (Test t : readOnly) {
t.a = 5;
}
for (Test t : values) {
System.out.println(t.a);
}
}
}
Выводится:
5
5
Важные соображения от @WMR answser.
Это зависит от того, будут ли потоки, которые начнется чтение вашей коллекции до или после заполнения. Если они запускаются, прежде чем вы их заполняете, у вас нет гарантий (без синхронизация), что эти потоки когда-либо увидит обновленные значения.
Причиной этого является память Java Модель, если вы хотите узнать больше, прочитайте раздел "Видимость" по этой ссылке: http://gee.cs.oswego.edu/dl/cpj/jmm.html
И даже если потоки запущены после того, как вы заполните свою коллекцию, вы возможно, придется синхронизировать, поскольку реализация коллекции может измениться его внутреннее состояние даже при чтении операции (спасибо Майкл Бар-Sinai, Я не знал таких коллекций существовало).
Еще одно интересное, прочитанное на тема concurrency, которая охватывает такие темы, как публикация объектов, видимость и т.д. намного подробнее книга Брайана Гетца Java concurrency в Практика.
Ответ 2
Это зависит от того, запускаются ли потоки, которые читают вашу коллекцию до или после ее заполнения. Если они запущены до того, как вы их заполнили, у вас нет гарантий (без синхронизации), что эти потоки когда-либо будут видеть обновленные значения.
Причиной этого является модель памяти Java, если вы хотите узнать больше, прочитайте раздел "Видимость" по этой ссылке: http://gee.cs.oswego.edu/dl/cpj/jmm.html
И даже если потоки запускаются после заполнения вашей коллекции, вам может потребоваться синхронизация, потому что ваша реализация коллекции может изменить свое внутреннее состояние даже при выполнении операций чтения (спасибо Michael Bar-Sinai, я не знал, что такие коллекции существуют в стандартном JDK).
Еще один интересный текст на тему concurrency, который охватывает такие темы, как публикация объектов, видимость и т.д., гораздо более подробно - книга Брайана Гетца Java concurrency на практике.
Ответ 3
В общем случае, вы должны. Это связано с тем, что некоторые коллекции меняют свою внутреннюю структуру во время чтения. Хорошим примером является LinkedHashMap, который использует порядок доступа. Но не задумывайтесь об этом:
В сопоставленных хэш-картах с привязкой к доступу, просто запрос карты с get является структурной модификацией Связанная хэш-карта javadoc
Если вы абсолютно уверены, что нет кешей, нет статистики статистики, нет оптимизаций, нет забавных вещей вообще - вам не нужно синхронизировать. В этом случае я бы поместил ограничение типа в коллекцию: не объявляйте коллекцию как карту (которая позволит LinkedHashMap), а как HashMap (для пуристов, заключительный подкласс HashMap, но это тоже может быть принято далеко...).
Ответ 4
Вам не обязательно, как объяснено в других ответах. Если вы хотите, чтобы ваша коллекция была доступна только для чтения, вы можете использовать:
yourCollection = Collections.unmodifableCollection(yourCollection);
(аналогичный метод существует для списка, набора, карты и других типов коллекций)
Ответ 5
Сама коллекция не имеет значения, но имейте в виду, что если то, что она имеет, не является неизменным, эти отдельные классы нуждаются в собственной синхронизации.