javamultithreadingunsafememory-fences

Java Unsafe.storeFence() documentation wrong?


Java 8 has added three fences to sun.misc.Unsafe.

I feel confused after I read their documentation.

So, I searched the web, and found this link.

According to the page above, I believe these methods add almost nothing in practice. Correct me if I'm wrong, roughly speaking, loadFence(), storeFence() and fullFence() correspond to volatile read, lazy write and volatile write respectively, although technically these fences are stronger than volatile variables. So loadFence() is an acquire fence, and storeFence() is a release fence, and fullFence() is full fence.

But then the documentation for storeFence() looks strange.

It says,

/**
 * Ensures lack of reordering of stores before the fence
 * with loads or stores after the fence.
 */
void storeFence();

That doesn't look like a release fence. How is it supposed to be used? Shouldn't it be

/**
 * Ensures lack of reordering of loads or stores before the fence
 * with stores after the fence.
 */
void storeFence();

I assume before means earlier and after means later.

EDIT

I don't mean "we don't use them in usual development" when I say these "fences add nothing in practice".

I mean, even without these methods in Unsafe, we can get these "fences". If I am correct, in practice, reading a dummy volatile has the effect of loadFence(), and writing a dummy volatile has the effect of fullFence(), and unsafe.putOrderedXXX() (or AtomicInteger.lazySet()) has the effect of storeFence().

They may have subtle difference, but in current implementation, they are exchangeable. (Seems implied by the link)

That is what I mean by "they add nothing new".

ANOTHER EDIT

This is already fixed.

See https://bugs.openjdk.java.net/browse/JDK-8038978

Thanks @john-vint


Solution

  • There is actually a diff for this in JDK9. There were similar questions that were asked and clarified:

    http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/84e19392365e

          /**
    !      * Ensures that loads before the fence will not be reordered with loads and
    !      * stores after the fence; a "LoadLoad plus LoadStore barrier".
    !      *
    !      * Corresponds to C11 atomic_thread_fence(memory_order_acquire)
    !      * (an "acquire fence").
    !      *
    !      * A pure LoadLoad fence is not provided, since the addition of LoadStore
    !      * is almost always desired, and most current hardware instructions that
    !      * provide a LoadLoad barrier also provide a LoadStore barrier for free.
           * @since 1.8
           */
          public native void loadFence();
    
          /**
    !      * Ensures that loads and stores before the fence will not be reordered with
    !      * stores after the fence; a "StoreStore plus LoadStore barrier".
    !      *
    !      * Corresponds to C11 atomic_thread_fence(memory_order_release)
    !      * (a "release fence").
    !      *
    !      * A pure StoreStore fence is not provided, since the addition of LoadStore
    !      * is almost always desired, and most current hardware instructions that
    !      * provide a StoreStore barrier also provide a LoadStore barrier for free.
           * @since 1.8
           */
          public native void storeFence();
    
          /**
    !      * Ensures that loads and stores before the fence will not be reordered
    !      * with loads and stores after the fence.  Implies the effects of both
    !      * loadFence() and storeFence(), and in addition, the effect of a StoreLoad
    !      * barrier.
    !      *
    !      * Corresponds to C11 atomic_thread_fence(memory_order_seq_cst).
           * @since 1.8
           */
          public native void fullFence();