Я много читал, но не нашел однозначного ответа.
У меня есть класс, который выглядит так:
public class Foo() {
private static final HashMap<String, HashMap> sharedData;
private final HashMap myRefOfInnerHashMap;
static {
// time-consuming initialization of sharedData
final HashMap<String, String> innerMap = new HashMap<String, String>;
innerMap.put...
innerMap.put...
...a
sharedData.put(someKey, java.util.Collections.unmodifiableMap(innerMap));
}
public Foo(String key) {
this.myRefOfInnerHashMap = sharedData.get(key);
}
public void doSomethingUseful() {
// iterate over copy
for (Map.Entry<String, String> entry : this.myRefOfInnerHashMap.entrySet()) {
...
}
}
}
И мне интересно, является ли потокобезопасным доступ к sharedData из экземпляров Foo (как показано в конструкторе и в doSomethingUseful ()). Многие экземпляры Foo будут создаваться в многопоточной среде.
Я предполагаю, что sharedData инициализируется в статическом инициализаторе и не изменяется после этого (только для чтения).
Что я прочитал, так это то, что неизменяемые объекты по своей природе безопасны для потоков. Но я видел это только в контексте переменных экземпляра. Являются ли неизменяемые статические переменные потокобезопасными?
Другая конструкция, которую я нашел, была ConcurrentHashMap. Я мог бы сделать sharedData типа ConcurrentHashMap, но HashMaps, которые он содержит, также должны иметь тип ConcurrentHashMap? В основном ..
private static final ConcurrentHashMap<String, HashMap> sharedData;
или
private static final ConcurrentHashMap<String, ConcurrentHashMap> sharedData;
Или было бы безопаснее (но дороже просто клонировать ())?
this.myCopyOfData = sharedData.get(key).clone();
ТИА.
(Статический инициализатор был отредактирован, чтобы дать больше контекста.)