Consider the code snippet
class A {
private Map<String, Object> taskMap = new HashMap<>();
private volatile Object[] tasksArray ;
// assume this happens on thread1
public void assignTasks() {
synchronized(taskMap){
// put new tasks into map
// reassign values from map as a new array to tasksArray ( for direct random access )
}
}
// assume this is invoked on Thread2
public void action(){
int someindex = <init index to some value within tasksArray.length>;
Object[] localTasksArray = tasksArray;
Object oneTask = localTasksArray[someindex];
// Question : is the above operation safe with respect to memory visibility for Object oneTask ?
// is it possible that oneTask may appear null or in some other state than expected ?
}
}
Question : is the operation Object oneTask = localTasksArray[someindex];
safe with respect to memory visibility for Object oneTask ?
is it possible that oneTask may appear null or in some other state than expected ?
My thoughts are these :
It is possible that thread2 may see oneTask
as null or in some state other than expected. This is because , even though the taskArray
is volatile
, and a read of this array will ensure proper visibility of the array itself , this does not ensure the visibility of the state internal to the object oneTask
.
The volatile
keyword only protects the field taskArray
which is a reference to an Object[]. Whenever you read or write this field, it will have consistent ordering. However, this doesn't extend to the array referenced nor the objects that array references.
Most likely you want AtomicReferenceArray instead.