[concurrency-interest] Extended access methods for Atomics (and AQS)

Boehm, Hans hans.boehm at hp.com
Thu Apr 15 20:46:56 EDT 2010

Even if we don't immediately give these any sort of formal semantics, it would be good to be clearer on what these are intended to mean.  That also affects the naming.  I think the semantics are currently unclear along a few dimensions:

1) Do they implicitly include fences?  I think we agree that the answer is no, i.e.

x1 = 1;
x2 = 2;

does not guarantee that the assignments to x1 and x2 become visible in order.  If this is correct, and I strongly believe it should be, I think we should avoid mentioning "fence" in the name.

2) Do they obey "cache coherency" rules, i.e. do the operations on a single variable appear totally ordered?  In particular, if we have x initially zero and:

Thread 1:
x = 1;
x = 2;

Thread 2:
r1 = x;
r2 = x;

Can we have r2 < r1?  Ordinary Java variables intentionally allow this.  When this was discussed in the context of C++0x atomic<T>, the feeling was that this was too weakly ordered to be useful.  I tent to agree.  (This does affect implementation cost, due both to the "reads kill" issue, and because a few architectures, notably Itanium, allow the unexpected behavior for ordinary loads.)  If this is disallowed, we probably shouldn't name this to suggest that it's equivalent to ordinary memory operations.  And I suspect it should be disallowed.

3) Can I really use "StoreOrder" variants to emulate "final"?  To get "final" semantics, I may need a fence or other special instruction on the store side, but I also need to make sure that when I read a pseudo-final field x.pf, the load of x and x.pf are dependent in the object code, and the hardware enforces ordering based on that dependency.  Current hardware usually does the right thing, and the compiler probably already does, too.  (Unless it does some sort of value speculation.) But this would be a very subtle change to the semantics of ordinary field accesses.  And getting the spec right is tricky.  In particular, I suspect we don't want to guarantee that the load of i in a[i] is implicitly ordered before that of a[i]. (Consider the case in which the compiler knows that a has exactly one element.)  I think this affects whether we want to mention "final" in the name.


> -----Original Message-----
> From: concurrency-interest-bounces at cs.oswego.edu 
> [mailto:concurrency-interest-bounces at cs.oswego.edu] On Behalf 
> Of David Holmes
> Sent: Thursday, April 15, 2010 5:50 AM
> To: Doug Lea; concurrency-interest at cs.oswego.edu
> Subject: Re: [concurrency-interest] Extended access methods 
> for Atomics (and AQS)
> Hi Doug,
> Doug Lea writes:
> > On 04/14/10 19:49, David Holmes wrote:
> >
> > > I think "InStoreorder" and "InRelaxedOrder" could easily be
> > misunderstood as
> > > relating to "total store ordering", or "relaxed memory models" or 
> > > any particular architecural memory model that uses that 
> kind of terminology.
> > >
> >
> > How about "setInStoreFencedOrder" (borrowing from one 
> version of our 
> > Fences API terminology)?  Note that this method is the same as 
> > existing "lazySet", which we adopted in part because people 
> wanted an 
> > obscure name, but it is so obscure that people don't even try to 
> > understand it. (Mainly because the "lazy" in lazySet is 
> deceptive. As 
> > a quality of implementation matter, store-fenced writes should be 
> > issued as soon as eligible, and are in hotspot and other JVMs. The 
> > sense of laziness is only wrt Sequential Consistency, which is a 
> > connection most people don't make.
> > Also, as Hans has pointed out a few times, the specs for 
> this method 
> > really ought to be spelled out along the lines of what we did for 
> > Fences.storeFence (aka orderWrites).)
> >
> > I don't see the problem with using the term "relaxed"
> > to mean "non-volatile, non-final", as introduced by the C++0x folks.
> > You need some term to denote this (just "non-volatile" is not quite 
> > accurate), so might as well observe precedent?
> If non-volatile doesn't accurately describe it then using the 
> term in the name would be misleading. In that case no simple 
> naming scheme seems to exist - whatever you call it, it will 
> be obscure and certainly non-intuitive. "relaxed" might be as 
> good a term as any other, though it leaves me wondering what 
> the difference is between a "relaxed" store and a plain store ?
> > > I guess this is somewhat better than Fences in that the 
> semantics of 
> > > the methods are easier to understand. But these are still methods 
> > > that the vast majority of programmers won't know when it 
> is valid to 
> > > use them. They will only discover that they seem faster 
> and so use 
> > > them
> regardless
> > :( Can we not "hide" them a bit better
> >
> > Well, the current options are maximally hidden and maximally ugly.
> > As people have already pointed out, those who do know when 
> to use them 
> > currently need to access them via Unsafe. Which, as always, bothers 
> > me. People increasingly take this path, making it even 
> harder to get 
> > constructions right, and making it impossible to run their code on 
> > platforms with security managers that prevent Unsafe access.
> > Would you rather see this practice continue?
> If these were the only choices - yes. But we can less 
> maximally hide by moving into a public API. I just don't 
> think it is a good idea to have these obscure, rarely usable 
> methods sitting along side the methods that get used all the time.
> > While I am at it ...
> >
> > The AtomicInteger draft contains store- and load- fenced 
> forms of CAS 
> > that represent the only "new" functionality introduced here:
> >    boolean compareAndSetInStoreOrder(int e, int v);
> >    int compareAndSetAndGet(int e, int v); These provide 
> orderings for 
> > CAS matching the ones for get and set. Some people have been asking 
> > for them for a long time (especially for Azul and Itanium, also 
> > probably worthwhile on ARM and POWER).
> > They are not at all commonly used, and are always 
> implementable using 
> > plain CAS. But defining them makes available for special 
> > intrinsification on some platforms.
> > This is a similar story as we have already for weakCompareAndSet, 
> > which I think these days is only specially intrinsified on 
> Azul's JVM.
> weakCAS has a much cleaner story than these relaxed orderings 
> - to allow for the "spurious" failure of ll/sc based 
> implementations. That's a lot simpler to explain than relazed 
> ordering stuff.
> Perhaps I'm missing a piece of the picture here. Is there 
> some formalism or methodology that can be readily used to 
> determine when an algorithm supports these weakly ordered 
> variants? If that's not the case then I confidently claim 
> that most uses of these methods will in fact be incorrect. 
> People (even those that should know better) will opt for the 
> seemingly more performant code over the correct code.
> David
> > -Doug
> > _______________________________________________
> > Concurrency-interest mailing list
> > Concurrency-interest at cs.oswego.edu
> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

More information about the Concurrency-interest mailing list