for review: 8236522: "always atomic" modifier for inline classes to enforce atomicity
John Rose
john.r.rose at oracle.com
Sat Mar 7 21:19:23 UTC 2020
On Mar 5, 2020, at 9:38 AM, Florian Weimer <fw at deneb.enyo.de> wrote:
>
> * John Rose:
>
>> http://cr.openjdk.java.net/~jrose/values/atomic-8236522
>
> NonTearable says this:
>
> 38 * <p> An inline instance of multiple components is said to be "torn"
> 39 * when two racing threads compete to update those components, and one
> 40 * thread updates some components while another thread updates other
> 41 * components. The resulting inline value stored in the heap might be
>
> I think this description is incorrect: a single writer, single reader
> scenario (with final fields in the inline class even) can also result
> in invalid values. See “Inline classes and the memory model” posted
> today; failed to spot the relevance of this older thread.
Thanks for the comment. The language here is unfortunate,
since “update” seems to suggest that the problem can’t occur
when one of the writes is the original initializing write. It
can, of course, as you point out. I’ll change “update” to
“write”. The tearing is observed by a subsequent read.
If the two writes race, and/or if the read races with one
of the writes (the JMM defines both as races) tearing
can occur.
> I think the actual goal here is to preserve the property that data
> races cannot observe out-of-thin-air values, like it is impossible
> with a subset of the primitive types? And also to support some
> concept of safe publication for inline classes?
Yes, that is the actual goal. Note that OOTA can come from
other sources besides tearing (of primitives or structs), so
we go with the more specific characterization of the problem
with value types. They are like longs, liable to have racing
updates to their subparts. As with longs, the experience of
the user is “hey, I didn’t store that value!”. Followed by,
“how am I going to enforce my invariants?”
The JVM implements this by applying whatever tactics
it already uses for volatile value fields (which like volatile
long fields are protected from tearing and hence OOTA).
Today these tactics are simply boxing under the covers,
so we get back to safe publication, instance by instance.
(The identity of the internal boxes continues to be hidden.)
In the future we might experiment with more performant
techniques, such as putting a seq-lock on the container.
A natural place for such a seq-lock is in the containing
object header, adjoined to the object’s natural monitor.
The effect of implementing NonTearable is to ensure,
at the declaration site of the type, that all heap variables
of the type, without exception (including in arrays) are
implemented with anti-tearing tactics. Non-heap
uses of the type are unaffected, so the value can still be
passed in registers and optimized without the need
for escape analysis.
— John
More information about the valhalla-dev
mailing list