У меня есть класс Java, к которому одновременно обращается множество потоков, и хочу убедиться, что он безопасен для потоков. Класс имеет одно закрытое поле, которое представляет собой карту строк в списки строк. Я реализовал Map как ConcurrentHashMap, чтобы гарантировать, что операции получения и размещения являются потокобезопасными:
public class ListStore {
private Map<String, List<String>> innerListStore;
public ListStore() {
innerListStore = new ConcurrentHashMap<String, List<String>>();
}
...
}
Итак, учитывая, что получение и установка на карту являются потокобезопасными, я беспокоюсь о списках, которые хранятся на карте. Например, рассмотрим следующий метод, который проверяет, существует ли данная запись в указанном списке в хранилище (я упустил проверку ошибок для краткости):
public boolean listEntryExists(String listName, String listEntry) {
List<String> listToSearch = innerListStore.get(listName);
for (String entryName : listToSearch) {
if(entryName.equals(listEntry)) {
return true;
}
}
return false;
}
Казалось бы, мне нужно синхронизировать все содержимое этого метода, потому что, если другой метод изменил содержимое списка в innerListStore.get (listName), пока этот метод итерирует по нему, возникнет исключение ConcurrentModificationException.
Это правильно, и если да, синхронизировать ли я на innerListStore или будет работать синхронизация на локальной переменной listToSearch?
ОБНОВЛЕНИЕ: Спасибо за ответы. Похоже, я могу синхронизировать в самом списке. Для получения дополнительной информации, вот метод add (), который может быть запущен в то же время, когда метод listEntryExists () выполняется в другом потоке:
public void add(String listName, String entryName) {
List<String> addTo = innerListStore.get(listName);
if (addTo == null) {
addTo = Collections.synchronizedList(new ArrayList<String>());
List<String> added = innerListStore.putIfAbsent(listName, addTo);
if (added != null) {
addTo = added;
}
}
addTo.add(entryName);
}
Если это единственный метод, который изменяет базовые списки, хранящиеся на карте, и никакие публичные методы не возвращают ссылки на карту или записи на карте, могу ли я синхронизировать итерацию в самих списках, и достаточно ли этой реализации add ()?