[concurrency-interest] Can a volatile read be reordered before a lazySet?

Gil Tene gil at azulsystems.com
Sat Dec 27 19:53:09 EST 2014


It is valid (e.g. per the JMM cookbook) for a JVM to implement a volatile read such that it prevents reordering with subsequent stores, but not with prior ones. Given this valid (and common) implementation, both cases asked about below can have a reordering happen between the lazySet and a subsequent (in program order) volatile get. Target machine (x86 or not) has nothing to do with it, as the compiler can (and will) do this reordering before any target machine code gets generated.

The only ordering that lazySet is actually known/required to provide will prevent the store operation from being reordered with any stores that came before it. There is nothing to prevent it from being pushed forward past other non-dependent stores, loads, or volatile loads. [The thing that stops it being pushed forward past a non-dependent volatile store is the volatile store's relationship with stores that precede it].

So:

theLong.lazySet(theLong.get() + 1);
Object o = theRef.get();

can be legitimately re-ordered by the compiler to:

x = theLong.get() + 1
Object o = theRef.get();
theLong.lazySet(x);

And the ping pong case:

ping.lazySet(1);
while (pong.get() == 0);

while (ping.get() == 0);
pong.lazySet(1);

can be legitimately reordered by the compiler to:

T1:
while (pong.get() == 0);
ping.lazySet(1);

T2:
while (ping.get() == 0);
pong.lazySet(1);

and can certainly result in a well deserved deadlock.

— Gil.


On Dec 23, 2014, at 6:17 PM, Thomas Kountis <tkountis at gmail.com<mailto:tkountis at gmail.com>> wrote:

David,

AFAIK all the atomic* members that Java provides, pretty much provide the same guarantees
as the volatile keyword does - which doesn't allow re-orderings on the compiler side, neither during execution.
If you look behind the covers, the fields that those two wrappers work on, are marked volatile as well. Also, lazy-set
is using the Unsafe.putOrdered...() which relies on a store-store barrier and will prevent any instruction re-ordering (as the name suggests).

So, to answer your question, I believe you are safe as far as it concerns re-orderings on your example.

t.

On Tue, Dec 23, 2014 at 10:50 PM, Dávid Karnok <akarnokd at gmail.com<mailto:akarnokd at gmail.com>> wrote:
Hello,

Given two atomic values held by an AtomicLong and an AtomicReference, is it possible the following two lines may be reordered?

theLong.lazySet(theLong.get() + 1);
Object o = theRef.get();

On X86, the memory model states that reads may be reordered with older writes to different locations, so the algorithm fragment above might be broken. For context, this code is part of a single-producer structure wich protects the use of theRef value with an ingress/egress counter pair.

I wonder if the same reordering might happen in a classical atomic ping-pong example:

ping.lazySet(1);
while (pong.get() == 0);

while (ping.get() == 0);
pong.lazySet(1);

i.e., in both threads, the while loops end up before the lazySet and thus deadlocking.

Best regards,
David Karnok


--
Best regards,
David Karnok


_______________________________________________
Concurrency-interest mailing list
Concurrency-interest at cs.oswego.edu<mailto:Concurrency-interest at cs.oswego.edu>
http://cs.oswego.edu/mailman/listinfo/concurrency-interest





_______________________________________________
Concurrency-interest mailing list
Concurrency-interest at cs.oswego.edu<mailto:Concurrency-interest at cs.oswego.edu>
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20141228/896100cd/attachment.html>


More information about the Concurrency-interest mailing list