Well, "yes, sort of". Your example works for String, because it is immutable.
Specifically, there is a happens-before relationship between the constructor's initialization of the final fields of the String and the subsequent publishing store of the result of the constructor. However, non-final fields have no such happens-before relationship with the publishing store. E.g. the cached hash field in String <https://github.com/bpupadhyaya/openjdk-8/blob/master/jdk/src/share/classes/java/lang/String.java#L117> may or may not be have been initialized when p.x is read. This [race on hash field initialization] has no visible side effect because of how the hash field is used in String: it caches the hash code, and will freshly compute the hash from the immutable char[] if the field holds a 0. So even if the initialization races with a call to hashCode() <https://github.com/bpupadhyaya/openjdk-8/blob/master/jdk/src/share/classes/java/lang/String.java#L1452> [e.g. a call to hashcode happens on another thread before the hash field is initialized, and the initialization overwrites the cached value with a 0], all that would happen is a recomputation of the same hash. The value returned by hashCode() won't change. But in other cases where non-final fields are involved, e.g. if p.x was a Foo with a non-final field y with a getter, p.x.getY() may return an uninitialized value after the get() returns a non-null p. On Friday, November 16, 2018 at 3:59:47 AM UTC-8, John Hening wrote: > > Hello, let's look at: > > > > class P { public String x; > } > > ConcurrentHashMap<Integer, P> x = new ConcurrentHashMap<>(); > > new Thread(() -> { // Thread 1 > x.put(1, new String("x")); // 1 > }).start(); > > new Thread(() -> { // Thread 2 > P p = x.get(1); // 2 > if(p != null){ > print(p.x); // 4 > } > }).start(); > > > > > If thread 2 observes p != null is it guaranteed by JMM that p.x is > initialized? For my eye, yes, because: > > Let's assume a such execution when p != null was true. It means that there > is a synchronize-with relation between x.put(1, new String("x")); --sw--> > x.get(). > Putting and getting an element from ConcurrentHashMap contain > synchronization access (and, actually, synchronization-with is between > them). > > In a result, there is a chain of happens-before relation: > > tmp = new String("x") --hb--> x.put(1, tmp) --hb--> x.get(1) --hb--> > read(p.x) > > > > > Yes? > > > > > > -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.