I'm designing a thread-safe container class called ConcurrentParamters
. here is what I tend to write:
Interfaces:
public interface Parameters {
public <M> M getValue(ParameterMetaData<M> pmd);
public <M> void put(ParameterMetaData<M> p, M value);
public int size();
}
public interface ParameterMetaData<ValueType> {
public String getName();
}
Implementation:
public final class ConcurrentParameters implements Parameters{
private final Map<ParameterMetaData<?>, Object> parameters;
private final volatile AtomicInteger size; //1, Not compile
{
size = new AtomicInteger();
parameters = new ConcurrentHashMap<>();
}
public static Parameters emptyParameters(){
return new ConcurrentParameters();
}
@Override
public <M> M getValue(ParameterMetaData<M> pmd) {
M value = (M) parameters.get(pmd);
return value;
}
@Override
public <M> void put(ParameterMetaData<M> p, M value){
parameters.put(p, value);
size.incrementAndGet();
}
@Override
public int size() {
return size.intValue();
}
}
I tried to make the AtomicInteger
field representing the size final, to ensure that no method can change the field poinitng to another object, as well as initialize it duriong consruction.
But since the container will be accessed concurrently, I need that any thread observes changes made by other. So, I tried to declared it volatile
as well in order ot avoid unnecessary synchronization
(I don't need mutual-exclusion).
I didn't compile. Why? Is there any reason? Does it make no sense to decalre a field that way? I thought it would be sesnsible... Maybe it is inheritly not safe?