What do you think is the best correct way for implementing the acquire part of a release/acquire pair in Java?
I'm trying to model some of the actions in an application of mine using classic release/acquire semantics (without StoreLoad
and without sequential consistency across threads).
There are a couple of ways to achieve the rough equivalent of a store-release in the JDK. java.util.concurrent.Atomic*.lazySet()
and the underlying sun.misc.Unsafe.putOrdered*()
are the most often cited approaches to do that. However there's no obvious way to implement a load-acquire.
The JDK APIs which allow
lazySet()
mostly usevolatile
variables internally, so their store-releases are paired with volatile loads. In theory volatile loads should be more expensive than load-acquires, and should not provide anything more than a pure load-acquire in the context of a preceding store-release.sun.misc.Unsafe
does not providegetAcquire()*
equivalents of theputOrdered*()
methods, even though such acquire methods are planned for the upcoming VarHandles API.Something that sounds like it would work is a plain load, followed by
sun.misc.Unsafe.loadFence()
. It's somewhat disconcerting that I haven't seen this anywhere else. This may be related to the fact that it's a pretty ugly hack.
P.S. I understand well that these mechanisms are not covered by the JMM, that they are not sufficient for maintaining sequential consistency, and that the actions they create are not synchronization actions (e.g. I understand that they for example break IRIW). I also understand that the store-releases provided by Atomic*/Unsafe
are most often used either for eagerly nulling out references or in producer/consumer scenarios, as an optimized message passing mechanism for some important index.
loadFence()
, or something else). – Bookbinder