It's good that sanity prevailed and that HB applies between inserts and
subsequent gets (and before that to any operations on the object such as
the construction).
Another way of looking at it is that almost *every *use of CHM would be
race if this wasn't the case! After all, very few objects are designed to
me unsafely published, and if there was no HB propagation through CHM, how
would you ever safely access an object put into a CHM by on thread and
retrieved by another. The only way it could work would be if there was some
other HB edge between the producer and consumer, e.g., you put a bunch of
things in the CHM, and then started some other threads (so there is a HB
edge due to thread start) and then accessed those objects - but you
couldn't access any *new *object inserted, and in that case why not just
pass the list of objects to the threads directly in any old non-concurrent
structure.
So the OP's original question is far from an obscure one: it applies to the
overwhelming majority of CHM use. CHM would be most unusable if it didn't
work like that.
On Sunday, November 18, 2018 at 12:02:47 PM UTC-5, Gil Tene wrote:
>
> Well, I was wrong on the internet. (Again).
>
> Vladimir is right, the happens-before is transitive. Regardless of the
> order of execution on either side, every field initialization (final or
> otherwise) happens-before the put(), and therefor happens-before any
> subsequent get() on any thread, such that the get()'ing thread cannot
> observe pre-initialization values in the value being put() in the CHM.
>
> For others that might follow the confusing weekend logic that led me to
> the mistake: I need to remind myself that it is complicated (and
> error-prone) to deduce negatives from positive observations. E.g. "happened
> before" just means "there is no happens-before that prohibited it from
> being observed this way" (from JLS 1.4.5: "...Informally, a read r is
> allowed to see the result of a write w if there is no happens-before
> ordering to prevent that read.").
>
> The process of making this mistake (for me) comes it comes from figuring
> out too many negatives in a row, as in when trying to fully figure out the
> meaning of "anti-anti-anti-missile-missile" in your head, without unfolding
> it on paper. It can lead to falsely jumping from "I have an example where I
> definitely saw A happen before B happened" to hb(A, B) instead of just the
> !hb(B, A) it actually means. And/or something like that backward.
>
> For me, these multi-deep-negatives thinking sequence often start with
> something informal like "so we know that another thread *can* see
> pre-initialized values of non-final fields if the reference to the object
> was published without an ordering operation of some sort" followed by "so
> since I know that is allowed, what is it in this stuff [like the CHM
> put()/get() example above] that actually prevents it from happening in this
> case?", then, after finding the concrete ordering operation [the volatile
> write and read] in the implementation but not stated *directly* in the
> contract (now we are in a two-deep negative assessment), taking the path of
> "I can construct a sequence where I *know* that an initialization of a
> field in an object happened before a publication of the object, and where
> without this ordering operation another thread could still see a value that
> predates that initialization, so if I remove this implementation-specific
> ordering operation this can still happen under this contract" takes me into
> a triple negative territory.
>
> The best thing to do is to erase the board and start from the other end...
>
> The contract's happens-before statement between the put() and subsequent
> non-null get()s, even while not directly saying anything about the
> relationships with program operations prior to the put(), does carry a
> transitive property that covers them. So the contract would require all
> future implementations to apply some ordering operation(s) that would still
> enforce the happens-before, including its transitive properties. What that
> operation would be doesn't matter, it is the implementor's responsibility
> to make sure it is there.
>
> On Sunday, November 18, 2018 at 2:37:27 AM UTC-8, Vladimir Sitnikov wrote:
>>
>> Gil>I'd be happy
>>
>> I wish you all the best. I truly adore the way you explain things.
>>
>> Gil>There is no contract I've found that establishes a
>> happens-before relationship between the initialization of non-final fields
>> in some object construction and the put of that object (or of some object
>> that refers to it) as a value into the CHM.
>>
>> In this case that contract is provided by JLS "17.4.3. Programs and
>> Program Order" and "17.4.5. Happens-before Order" .
>> TL;DR: "If x and y are actions of the same thread and x comes before y in
>> program order, then hb(x, y)."
>>
>> Let me take an example:
>>
>> class Wrapper {
>> int value;
>> }
>> static CHM map;
>>
>> Thread1:
>> val w = new Wrapper();
>> w.value=42;
>> map.put("wrap", w);
>>
>> Thread2:
>> val u = map.get("wrap");
>> if (u != null) { println(u.value); }
>>
>> 1) In thread 1 there's happens-before between write "value=42", and write
>> of "w" into the map since "program order implies happens-before"
>> 2) CHM provides happends-before for non-null retrieval of the value
>> 3) "retrieval of the value u" happens-before "read of u.value" since
>> "program order implies happens-before"
>>
>> The happens-before order is a partial order, so it is transitive, so
>> 1+2+3 gives "write of value=42 happens-before read of u.value".
>> The key point of having a CHM is to have 2 (happens-before across
>> threads) which is not provided automatically if simple HashMap is used.
>>
>> What do you think?
>>
>> Gil>It is true that* in current implementation* a put() involves a
>> volatile store
>>
>> JavaDoc contract is there, so CHM would provide "happens-before relation
>> between update and non-null retrieval" in future one way or another.
>>
>> Vladimir
>>
>
--
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 [email protected].
For more options, visit https://groups.google.com/d/optout.