Reputation: 23
When I read jsr-133-faq, in question "How do final fields work under the new JMM?", it said:
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;
int j = f.y;
}
}
}
The class above is an example of how final fields should be used. A thread executing reader is guaranteed to see the value 3 for f.x, because it is final. It is not guaranteed to see the value 4 for y, because it is not final.
This makes me confused, because the code in writer is not safe publication, thread executing reader may see f is not null, but the constructor of the object witch f referenced is not finished yet, so even if x is final, the thread executing reader can not be guaranteed to see the value 3 for f.x.
This is the place where I'm confused, pls correct me if i am wrong, thank you very much.
Upvotes: 2
Views: 676
Reputation: 1290
This is the whole point, and that is what's great about about final fields in the JMM. Yes, compiler can generally assign a reference to the object before the object is even fully constructed, and this is unsafe publication because the object may be accessed in a partially-constructed state. However, for final fields, the JMM (and the compiler) guarantees that all final fields will be prepared first, before assigning the reference to the object. The publication may still be unsafe and the object still only partially constructed when a new thread accesses it, but at least the final fields will be in their expected state. From chapter 16.3 in Java Concurrency in Practice:
Initialization safety makes visibility guarantees only for the values that are reachable through final fields as of the time the constructor finishes. For values reachable through nonfinal fields, or values that may change after construction, you must use synchronization to ensure visibility.
I also recommend reading chapter 16.3 for more detail.
Upvotes: 3