[concurrency-interest] JDK 9's compareAndSet vs compareAndExchange

Dávid Karnok akarnokd at gmail.com
Fri Sep 23 03:11:20 EDT 2016


Thanks for the information.

FYI, I do have places where compareAndExchange is useful and not part of a
loop:

public static boolean setOnce(VarHandle h, Object instance, Subscription s)
{
    Subscription o = (Subscription)h.compareAndExchange(instance, null, s);
    if (o != null) {
        s.cancel();
        if (o != CANCELLED) {
            CatchAll.onError(new IllegalStateException("Subscription
already set!"));
        }
        return false;
    }
    return true;
}



2016-09-22 17:06 GMT+02:00 Vitaly Davidovich <vitalyd at gmail.com>:

>
>
> On Thu, Sep 22, 2016 at 10:20 AM, Aleksey Shipilev <shade at redhat.com>
> wrote:
>
>> Hi,
>>
>> Somewhat counter-intuitively, reusing compareAndExchange return value as
>> the basis for retry is slower than re-reading actual value for
>> compareAndSet. Because under contention, the overall progress depends on
>> the width on the "collision window" for your RMW operation:
>>  https://bugs.openjdk.java.net/browse/JDK-8141640
>
> Interesting result.  What CPU was this test done on, if you recall? The #
> of cycles in the "collision window" in that benchmark is fairly small (just
> a bunch of cheap ALU instructions and register-to-register movs that ought
> to be renamed).  Did you look at any PMU counters that would back up the
> theory?
>
> Thanks
>
>>
>>
>> compareAndExchange is useful when you *have* to have the "witness value"
>> against which you failed. Choosing compareAndExchange over compareAndSet
>> within the loop is futile. Choosing compareAndExchange *instead* of
>> compareAndSet + re-reads is sane, e.g. in
>> https://github.com/boundary/high-scale-lib/blob/master/src/
>> main/java/org/cliffc/high_scale_lib/NonBlockingHashMap.java#L583
>>
>> Thanks,
>> -Aleksey
>>
>> On 09/22/2016 03:35 PM, Dávid Karnok wrote:
>> > JDK 9's VarHandle API (and AtomicXXX classes) specify the new
>> >  compareAndExchange() method. Traditionally, I wrote CAS loops like
>> this:
>> >
>> > public static long getAddAndCap(AtomicLong requested, long n) {
>> >     for (;;) {
>> >         long current = requested.get();
>> >
>> >         if (current == Long.MAX_VALUE) {
>> >            return Long.MAX_VALUE;
>> >         }
>> >         long next = current + n;
>> >         if (next < 0L) {
>> >             next = Long.MAX_VALUE;
>> >         }
>> >         if (requested.compareAndSet(current, next)) {
>> >             return current;
>> >         }
>> >     }
>> > }
>> >
>> > Now I can write this:
>> >
>> > public static long getAddAndCap(AtomicLong requested, long n) {
>> >     long current = requested.get();
>> >     for (;;) {
>> >
>> >         if (current == Long.MAX_VALUE) {
>> >            return Long.MAX_VALUE;
>> >         }
>> >         long next = current + n;
>> >         if (next < 0L) {
>> >             next = Long.MAX_VALUE;
>> >         }
>> >         long actual = requested.compareAndExchange(current, next);
>> >         if (actual == current) {
>> >            return current;
>> >         }
>> >         current = actual;
>> >     }
>> > }
>> >
>> > I'm not sure I could JMH benchmark these under JDK 9 now so my question
>> > is whether the latter pattern has lower overhead (on x86) since it
>> > reuses the value returned by the underlying LOCK CMPXCHG instead of
>> > re-reading the target field again (or the JIT was always smart enough to
>> > detect the unnecessary re-read with compareAndSet; or the hardware is
>> > smart enough by doing speculative reads in this case to hide its
>> latency ?).
>> >
>> > --
>> > Best regards,
>> > David Karnok
>> >
>> >
>> > _______________________________________________
>> > 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
>>
>>
>


-- 
Best regards,
David Karnok
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20160923/5b8e8adc/attachment-0001.html>


More information about the Concurrency-interest mailing list