Где-то в моем многопоточном коде у меня есть карта (доступ к которой осуществляется несколькими потоками), объявленная так:
private Map<Foo, Integer> fooMap =
Collections.synchronizedMap(new HashMap<Foo, Integer>());
Этот же класс предоставляет открытый метод
public Collection<Foo> getFooList() {
return fooMap.keySet();
}
В другом месте моего кода я перебираю коллекцию, возвращаемую getFooList()
.Мне известно, что большинство операций на синхронизированной карте являются поточно-ориентированными, за исключением одного итерации, которая должна быть явно синхронизирована.Я реализовал это следующим образом:
synchronized(bar.getFooList()) {
for (Foo foo : bar.getFooList()) {
// do stuff with foo
}
}
Время от времени я получаю ConcurrentModificationException
для оператора for
.Мне интересно, синхронизируюсь ли я с неправильным экземпляром класса. Должен ли я синхронизироваться с картой, а не с ее набором ключей?Опять же, я действительно не хочу открывать всю карту другим классам (она является закрытой по какой-то причине).
Как перебрать набор ключей потокобезопасным способом, без необходимости выставлятьвся карта?