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

Dávid Karnok akarnokd at gmail.com
Thu Sep 22 09:35:42 EDT 2016


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20160922/e55870cf/attachment.html>


More information about the Concurrency-interest mailing list