Whilst trying to understand how SubmissionPublisher
(source code in Java SE 10, OpenJDK | docs), a new class added to the Java SE in version 9, has been implemented, I stumbled across a few API calls to VarHandle
I wasn't previously aware of:
fullFence
, acquireFence
, releaseFence
, loadLoadFence
and storeStoreFence
.
After doing some research, especially regarding the concept of memory barriers/fences (I have heard of them previously, yes; but never used them, thus was quite unfamiliar with their semantics), I think I have a basic understanding of what they are for. Nonetheless, as my questions might arise from a misconception, I want to ensure that I got it right in the first place:
Memory barriers are reordering constraints regarding reading and writing operations.
Memory barriers can be categorized into two main categories: unidirectional and bidirectional memory barriers, depending on whether they set constraints on either reads or writes or both.
C++ supports a variety of memory barriers, however, these do not match up with those provided by
VarHandle
. However, some of the memory barriers available inVarHandle
provide ordering effects that are compatible to their corresponding C++ memory barriers.#fullFence
is compatible toatomic_thread_fence(memory_order_seq_cst)
#acquireFence
is compatible toatomic_thread_fence(memory_order_acquire)
#releaseFence
is compatible toatomic_thread_fence(memory_order_release)
#loadLoadFence
and#storeStoreFence
have no compatible C++ counter part
The word compatible seems to really important here since the semantics clearly differ when it comes to the details. For instance, all C++ barriers are bidirectional, whereas Java's barriers aren't (necessarily).
- Most memory barriers also have synchronization effects. Those especially depend upon the used barrier type and previously-executed barrier instructions in other threads. As the full implications a barrier instruction has is hardware-specific, I'll stick with the higher-level (C++) barriers. In C++, for instance, changes made prior to a release barrier instruction are visible to a thread executing an acquire barrier instruction.
Are my assumptions correct? If so, my resulting questions are:
Do the memory barriers available in
VarHandle
cause any kind of memory synchronization?Regardless of whether they cause memory synchronization or not, what may reordering constraints be useful for in Java? The Java Memory Model already gives some very strong guarantees regarding ordering when volatile fields, locks or
VarHandle
operations like#compareAndSet
are involved.
In case you're looking for an example: The aforementioned BufferedSubscription
, an inner class of SubmissionPublisher
(source linked above), established a full fence in line 1079 (function growAndAdd
; as the linked website doesn't support fragment identifiers, just CTRL+F for it). However, it is unclear for me what it is there for.
plain -> opaque -> release/acquire -> volatile (sequential consistency)
. – Eugene