Java Concurrency in Practice says you can safely publish an effectively immutable object (say, a Date object that you construct and never change again) by sticking it into a synchronized collection like the following (from the book, page 53):
public Map<String, Date> lastLogin =
Collections.synchronizedMap(new HashMap<String, Date>())
I understand that any Date object put into this map will be visible (at least in its initial but completely constructed state) once placed into this synchronized map, but only once other threads can obtain the reference to this Map object.
Since the reference field lastLogin has none of the properties of fields that guarantee visibility (final, volatile, guarded, or initialized by a static initializer), I think that it's possible the map itself will not show up in a completely constructed state to other threads, therefore putting the cart before the horse. Or am I missing something?
TL: DR — Yes, Java Concurrency in Practice is still valid and one of the best books to learn Java multithreading and concurrency concepts.
Concurrency is the ability to run several or multi programs or applications in parallel. The backbone of Java concurrency is threads (a lightweight process, which has its own files and stacks and can access the shared data from other threads in the same process).
The simplest way to avoid problems with concurrency is to share only immutable data between threads. Immutable data is data which cannot be changed. To make a class immutable define the class and all its fields as final. Also ensure that no reference to fields escape during construction.
Safe publication makes all the values written before the publication visible to all readers that observed the published object. It is a great simplification over the JMM rules of engagement with regards to actions, orders and such.
Your suspicion is half right, in that the value of lastLogin
is not guaranteed to be visible to other threads. Because lastLogin
is not volatile
or final
, another thread may read it as null
.
However, you do not need to worry that other threads will see an incomplete version of the map. Collections.synchronizedMap(...)
returns an instance of a private class with final
fields. JLS section 17.5 says:
The usage model for final fields is a simple one: Set the final fields for an object in that object's constructor; and do not write a reference to the object being constructed in a place where another thread can see it before the object's constructor is finished. If this is followed, then when the object is seen by another thread, that thread will always see the correctly constructed version of that object's final fields.
SynchronizedMap
follows these rules, so another thread reading lastLogin
will either read null
or a reference to the fully constructed map, never a reference to an incomplete or unsafe version of the map.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With