RFR: JDK-8074578 Document memory visibility effects of some Unsafe methods
David Holmes
david.holmes at oracle.com
Tue Mar 10 01:30:43 UTC 2015
On 10/03/2015 2:21 AM, Martin Buchholz wrote:
> On Mon, Mar 9, 2015 at 4:13 AM, David Holmes <david.holmes at oracle.com
> <mailto:david.holmes at oracle.com>> wrote:
>
> On 9/03/2015 7:27 PM, Andrew Haley wrote:
>
>
> But who is to say that is the specification for the Unsafe API?
>
>
> It's for us to say!
I meant specifically the choice of the specification, not the right to
suggest one.
> The public API's have a specification for what they provide to the
> programmer. On what basis are we assigning that same specification
> to Unsafe API? The Unsafe API has to meet the requirements of the
> public APIs that use it, but that doesn't mean it necessarily
> should have the same specification as those APIs.
>
>
> We already have lots of code that implicitly depends on volatile
> read/write visibility, especially in j.u.c.
> Most obviously, how do you implement compareAndSet methods without the
> same visibility guarantees on the Unsafe equivalents?
Obviously Unsafe has to be implemented in a way that satisfies the j.u.c
routines that use it.
> My spec change only documents what "everyone already knows to be true".
> Another way of looking at it is that the Unsafe methods are a low-level
> optimization of the equivalent j.u.c.a. objects without requiring memory
> allocation.
The public API methods specify memory ordering semantics so that the end
programmer can use those to reason about their use of j.u.c components.
The implementation of j.u.c has to satisfy its specified semantics.
The current implementation of j.u.c uses Unsafe operations that in turn
utilize JVM operations. The JVM operations have memory synchronization
affects that are stronger than required by j.u.c, and so satisfy them.
So the question is: should Unsafe specify the expectations of its j.u.c
client (what you propose); or should it specify what the JVM
implementations provide; or should it not actually specify anything in
this regard knowing that the implementation is required to correctly
implement the public APIs? I don't see much point in pushing down the
spec from the public APIs to the Unsafe API. To me it suffices to say
that the Unsafe methods must correctly implement the requirements of the
public API without specifying that in specific terms of volatile
read/writes (which it doesn't actually use) or full bi-directional
fences (which it does use). It's not as if Unsafe were a public API for
which we might switch in implementations from different providers and
hence we need a clear specification for those implementors to follow.
But if you think it important that these Unsafe methods say something
about memory synchronization then the wording still needs to make clear
what "volatile" is assumed to be being accessed. In particular the j.u.c
usage always passes the offset of a variable that is volatile - hence
getting volatile read/write semantics. But you can pass the Unsafe
methods the offset for a variable that is not declared volatile - so
what then? Should the specification state that the offset is
assumed/expected to that for a volatile variable and hence it provides
volatile read/write only if that variable is volatile? Or should we
state something more generic as in:
"This operation reads the Java variable at the given offset with
volatile load semantics, and writes it with volatile store semantics."
That doesn't force the variable to be volatile but does require Unsafe
to act as if it were. The wording is also similar to that used in
getObjectVolatile/putObjectVolatile. (It also doesn't attempt to the
address the debate as to whether there is any volatile write on failure
- should it?)
Or should we say something else?
Cheers,
David
More information about the core-libs-dev
mailing list