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.

Reply via email to