JMM and final field freeze
Internally, someone had this question yesterday:
public SomeClass {
private final LinkedHashMap map = new LinkedHashMap();
public SomeClass() {
init();
}
private void init() {
// just create objects and map.put() –
// no tricks here, no this escaping, etc
}
// A read method
public Object get(Object key) {
return map.get(key);
}
// etc…
}
And the question is:
The map is never mutated after construction. The field is declared final. Are the read methods thread-safe and guaranteed to show you the map with all values? If not, is an additional memory barrier required to guarantee this?
I think pretty much everyone agreed that readers are guaranteed to see the map instance but there was some question about whether the puts to the map during init() can be reordered such that they are not thread-safe with respect to the get()s.
After many folks weighed in, the consensus is that yes, the reads are definitely thread-safe even in the absence of an additional memory barrier.
One goal of JSR 133 (which defines the Java Memory Model) is to preserve initialization safety. The JSR 133 FAQ says:
If an object is properly constructed (which means that references to it do not escape during construction), then all threads which see a reference to that object will also see the values for its final fields that were set in the constructor, without the need for synchronization.
I think that’s a pretty good summary of the intent. The concept of whether changes to final fields are visible at end of construction is explicitly talked about in the memory model semantics paper as well in the section on “informal semantics of final fields”:
F1 When a final field is read, the value read is the value assigned in the constructor.
F2 Assume thread T1 assigns a value to a final field f of ob ject X defined in class C. Assume that T1 does not allow any other thread to load a reference to X until after the C constructor for X has terminated. Thread T2 then reads field f of X. Any writes done by T1 before the class C constructor for ob ject X terminates are guaranteed to be ordered before and visible to any
reads done by T2 that are derived from the read of f.
Java Concurrency in Practice also mentions this in section 16.3:
Initialization safety guarantees that for *properly constructed* objects, all threads will see the correct values of final fields that were set by the constructor, regardless of how the object is published. Further, any variables that can be *reached* through a final field of a properly constructed object (such as the elements of a final array or the contents of a HashMap referenced by a final field) are also guaranteed to be visible to other threads.
For objects with final fields, initialization safety prohibits reordering any part of construction with the initial load of a reference to that object. All writes to final fields made by the constructor, as well as to any variables reachable through those fields, become “frozen” when the constructor completes, and any thread that obtains a reference to that object is guaranteed to see a value that is at least as up to date as the frozen value. Writes that initialize variables reachable through final fields are not reordered with operations following the post-construction freeze.
I find the formal definition of the final field freeze semantics to be fairly impenetrable, so I’ll just trust that they say formally what is stated informally above.
Final fields are ever so important and useful. Whenever possible, strive to make your fields final. One tip for this is to enable a Save Action in Eclipse (or your IDE of choice) that automatically attempts to make fields final if possible so you can’t forget!

Hi! My name is Alex Miller and I live in St. Louis. I write code for a living and currently work for
I would disagree and say that the reads are not thread-safe. The field someClass.map will be visible, of course. But LinkedHashMap itself is not thread-safe and has non-final fields. Thus any writes to those fields may be not visible in other threads. Writing to a final field is no memory barrier (at least in the JMM, in real-world implementations it may be).
In the quotes that you posted I can’t find anything about writes to final members influencing the visibility of writes to non-finals. It’s just about the visibility of finals: a final member is only visible to other threads after the completion of the constructor. (someClass.map is visible in init() anyway, because init() runs in the same thread)
The JLS offers a very simple summary of the JMM:
* An unlock on a monitor happens-before every subsequent lock on that monitor.
* A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
* A call to start() on a thread happens-before any actions in the started thread.
* All actions in a thread happen-before any other thread successfully returns from a join() on that thread.
* The default initialization of any object happens-before any other actions (other than default-writes) of a program.
It’s even simpler if you ignore the points 3 and 4, which are not that interesting most of the time.
Well, I’m pretty sure I’m right, but then I’ve learned to never fully trust my understanding of the JMM. Regarding the quotes, the JCIP quote specifically gives an example of the contents of a final Map being visible after construction.
If you continue reading down the page on that JLS reference you gave, you’ll come to the section on final fields (17.5) which gives much weight to my argument. Quotes like:
“Final fields also allow programmers to implement thread-safe immutable objects without synchronization. A thread-safe immutable object is seen as immutable by all threads, even if a data race is used to pass references to the immutable object between threads.”
“Set the final fields for an object in that object’s constructor. 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. It will also see versions of any object or array referenced by those final fields that are at least as up-to-date as the final fields are.”
That seems very clear to me. Happens before is great but it is NOT sufficient (according to the JLS page you referenced) to define proper behavior. The actual JMM takes other things into account.
I agree with Alex.
But even without the final it would be ‘threadsafe’. Eventually the object needs to be published to make the reference visible to other threads. This publication is going to introduce a happens before relation between the initialization of the hashmap and the usage of the hashmap because the happens before rules are transitive.
http://pveentjer.wordpress.com/2008/04/02/jmm-constructors-dont-have-visiblity-problems/
But using finals is better, you don’t need to depend on an external environment to resolve the issues. And making stuff final also is a good form of documentation.
It really depends on the reference to the SomeClass instance. Is *that* safely published (i.e. in a final field) to all threads? If yes then it’s fine, whatever you put in init() will be visible in other threads calling get().
As Peter correctly points out you don’t even need to declare the map field final for it to be threadsafe, and “effectively” immutable (since it is never written to after init()).
Dhanji.
Alex is correct, but it is not surprising that this is confusing enough to get different answers — this is deliberately exploring the boundaries of the memory model.
One unstated assumption is that the keys and values in the map are individually thread-safe or effectively immutable.
I don’t buy Peter’s argument, though. While the elements of the map may eventually “become visible” without final, it may be seen to violate some obvious invariants in the absence of the final or other ordering guarantees. For example, you could iterate the keys of the LHM but have containsKey() return false for one of those keys. That would clearly be confusing.
Hi Brian,
I think you have overlooked a part of my argument or I didn’t express myself clearly, because a safe publication need some kind of synchronization action like a volatile or a lock for example.
If an object has publication problems (all fields are normal and not volatile/final/used in a synchronized context) the object can be safely used in a multithreaded environment if:
-in some point in time this object is published correctly by using volatile/final/synchronized context and not before
- the object is not changed after this publication
The ordering gurantees for the volatile write/synchronized unlock are so strong that instruction before them can’t jump over them, so constructor code for example is not allowed to be executed after this publication, The same goes for the ordering gurantees of the volatile read/synchroned lock: the ordering guarantees are so strong that instructions that come after them can’t jump in front of them.
In your book have written a small chapter about it: piggybacking on synchronization. And I think it is one of the most powerfull features of the new JMM (since objects with publication problems can be used safely, for example by using a blockingqueue or concurrentmap).
Occording to the JMM in the case of the SomeClass (without final map):
1) there is a happens before relation between the creation of the someclass and the publication (using a volatile variable for example) : program order rule
2) there is a happens before relation between the write and read of a volatile variable (volatile variable rule)
3) there is a happens before relation between the read of the volatile variable, and the usage of the internals
And since the happens before rules are transitive, there is a happens before relation between action1 and action3.
So the SomeClass can safely be used in a multithreaded environment if it is published safely (and not changed after construction).
If I got this wrong, it would mean that there is a serious holes in my understanding of the JMM and I would like to understand what I’m missing.
You are right, the objects reachable by a final field have the same visibilty as the final field itself. I didnt know that.
Peter, are you assuming that the SomeClass object is itself safely published? You didn’t state that assumption. If so, though, this is right, as the state of the SomeClass *is* the state of the Map.
At first I agreed with Tim Jansen, that LinkedHashMap does not use a final field, and therefore is not thread-safe without using synchronization.
But after actually reading the original JSR133 spec, I saw
Figure 22: Transitive guarantees from final fields
and it shows this exact example.
So I agree with Alex, and it is thread safe.