I've read around quite a bit but haven't found a definitive answer.
I have a class that looks like this:
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()) {
...
}
}
}
And I'm wondering if it is thread safe to access sharedData from instances of Foo (as is shown in the constructor and in doSomethingUseful()). Many instances of Foo will be created in a multi-threaded environment.
My intention is that sharedData is initialized in the static initializer and not modified thereafter (read-only).
What I've read is that immutable objects are inherently thread safe. But I've only seen this in what seems to be the context of instance variables. Are immutable static variables thread safe?
The other construct I found was a ConcurrentHashMap. I could make sharedData of type ConcurrentHashMap but do the HashMaps it contains also have to be of type ConcurrentHashMap? Basically..
private static final ConcurrentHashMap<String, HashMap> sharedData;
or
private static final ConcurrentHashMap<String, ConcurrentHashMap> sharedData;
Or would it be safer (yet more costly to simply clone())?
this.myCopyOfData = sharedData.get(key).clone();
TIA.
(Static initializer has been edited to give more context.)
Aren't you are actually asking if the static initialization of
sharedData
is thread safe and only executed once?And yes, that is the case.
Of course many people here have correctly pointed out that the contents of
sharedData
can still be modified.No. Except if they are immutable.
The only thing they do is
Still if your attribute is mutable then it is not thread safe.
See also: Do we synchronize instances variables which are final?
It is exactly the same except they are class level.