I recently got confused when i referred to JMM for guarantees associated with "final". Here is an excerpt and example from JMM
Figure 4 gives an example that demonstrates how final fields compare to normal fields. The class FinalFieldExample has a final int field x and a non-final int field y. One thread might execute the method writer(), and another might execute the method reader(). Because writer() writes f after the object’s constructor finishes, the reader() will be guaranteed to see the properly initialized value for f.x: it will read the value 3. However, f.y is not final; the reader() method is therefore not guaranteed to see the value 4 for it
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
My confusion is that is an object 'Obj' has final and non-final fields is fully initialized and is being referenced by a Thread 'T', T will only see correct values for final fields ? What about non-final fields that are not mutated after construction. I understand that if they are mutated after construction thread 'T' might not see new value ( unless the field is a volatile ). But i am what if the field is non-final and non-volatile and is not mutated after construction ?
How does JVM implements guarantees associated with 'final' ? E.g for volatile there are memory barriers.