Wednesday, June 1, 2011

How do final fields work under the new JMM?

The values for an object's final fields are set in its constructor. Assuming the object is constructed "correctly", once an object is constructed, the values assigned to the final fields in the constructor will be visible to all other threads without synchronization. In addition, the visible values for any other object or array referenced by those final fields will be at least as up-to-date as the final fields.

What does it mean for an object to be properly constructed? It simply means that no reference to the object being constructed is allowed to "escape" during construction. (See Safe Construction Techniques for examples.)  In other words, do not place a reference to the object being constructed anywhere where another thread might be able to see it; do not assign it to a static field, do not register it as a listener with any other object, and so on. These tasks should be done after the constructor completes, not in the constructor.

Now lets see the example:

class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;


Now suppose we call the constructor:

new FinalFieldExample();

After the construction, it is guaranteed that x=3 by the thread as x is final. But y's initialization is not guaranteed. It may be seen as 0 or 4. So prior JMM was faulty but now final is "really" final.


Difference between new JMM final and old one

Java in old JMM never guaranteed initialization of final objects. But in JMM if final value is set to 3, it will be set, no matter what.

But what if some object like date or array is declared final? If some object is declared final, than all the fields into it and all memory parts of that object are guaranteed to be initialized in new JMM.

So, you can have a final pointer to an array and not have to worry about other threads seeing the correct values for the array reference, but incorrect values for the contents of the array. Again, by "correct" here, we mean "up to date as of the end of the object's constructor", not "the latest value available".

Does final guarantee latest value?


Note: Final values are set by JMM only once. So the "first time initialization" is guaranteed but the latest value is not guaranteed, and of-course final in java really mean that.

Now, having said all of this, if, after a thread constructs an immutable object (that is, an object that only contains final fields), you want to ensure that it is seen correctly by all of the other thread, you still typically need to use synchronization or some other technique to ensure no caching and mutual exclusion. There is no other way to ensure, for example, that the reference to the immutable object will be seen by the second thread. The guarantees the program gets from final fields should be carefully tempered with a deep and careful understanding of how concurrency is managed in your code.


Where can't you see effect of final?


If FinalFieldExample's constructor looked like this:

public FinalFieldExample() { // bad!
x = 3;
y = 4;
// bad construction - allowing this to escape
global.obj = this;

then threads that read the reference to this from global.obj are not guaranteed to see 3 for x.

No comments:

Post a Comment