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