I have some doubd with ArrayList safe publication.
I have code:
private final Map<Long, SomeStuff> map = new ConcurrentHashMap<>();
//Called by Thread 1
public void write() {
List list = new ArrayList<>();
for (int i = 0; i <100 ; i++) {
list.add(new SomeStuff(i))
}
map.put(1L,list)
}
// Called by Thread 2
public void read() {
List list = map.get(1L);
}
Will the ivocation of map.get(1L) return ArrayList in correct state(has correct size for example)?
What about elements of ArrayList? Will the elements be published safely?
I noticed that ConcurrentHashMap.put
guarded by lock on Node,that will be modified, but ConcurrentHashMap.get
performs throught Unsafe.getObjectVolatile
.
And i think that ArrayList might be published unsafety
Thanks!
The short answer: yes, the ArrayList object will be published safely along with its elements.
You shouldn't generally look into the class's source code and make any conclusions about thread safety yourself, but you should rather rely on guarantees that are given in a class/interface javadoc. I strongly recommend the book "Java Concurrency in Practice" that elaborates on such approaches.
The ConcurrentMap (which is implemented by ConcurrentHashMap) interface states:
Memory consistency effects: As with other concurrent collections, actions in a thread prior to placing an object into a ConcurrentMap as a key or value happen-before actions subsequent to the access or removal of that object from the ConcurrentMap in another thread.
which means that anything that happened before the "put" is visible to the thread that makes a "get" on the same object afterwards. Which means that in the case the "get" happens after the "put" then your second thread will see a "good" ArrayList object with all its elements.
And here is a note that is not about safe publication, but just a thing to remember:
ArrayList itself (and possibly your elements' class) is not thread-safe. But you can be OK with it as long as you don't modify those objects from some other threads. As described in the "Java Concurrency in Practice" book - this is "Serial Thread Confinement" which means that you can safely publish a non-thread-safe object from one thread to another thread thus transferring "ownership" from a thread to a thread and thus making the object "Thread Confined" at a particular point in time. As I said it applies only if you make sure it is not modified from somewhere else.