2

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.

azs1478963
  • 23
  • 2
  • 1
    `thread executing reader may see f is not null, but the constructor of the object witch f referenced is not finished yet` This can't happen, the assignment happens __after__ the constructor ran to completion and no exception was thrown. – tkausl Apr 24 '18 at 16:36
  • 1
    Which mechanism ensures the occurrence of the assignment happens after the constructor ran to completion?[In Jeremy Manson's blog](http://jeremymanson.blogspot.com/2008/05/double-checked-locking.html), he said that compiler transformations can change the code around so that the code in the Helper constructor occurs after the write to the helper variable. I think the code in jsr-133-faq is the same scene with the code in Jeremy Manson's blog. – azs1478963 Apr 25 '18 at 01:09

1 Answers1

3

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.

bhh1988
  • 1,262
  • 3
  • 15
  • 30
  • it seems to me that in 2014 (10 years after the book you are mentioning) the JMM specifications have changed and as long as there is one final field, it sets a barrier that doesn't allow the object to be visible (i.e. referenced) until it is properly constructed. https://hg.openjdk.java.net/jdk9/jdk9/hotspot/file/ae45df3285c9/src/share/vm/opto/parse1.cpp#l930 – Jernej Filipčič Sep 12 '22 at 15:24