akhil_mittal
akhil_mittal

Reputation: 24157

How CAS related changes in AtomicLong class in Java 8 work?

Prior to Java 8 the code for CAS in AtomicLong class was:

public final long incrementAndGet() {
    for (;;) {
        long current = get();
        long next = current + 1;
        if (compareAndSet(current, next))
          return next;
    }
}

But now it has been changed to single intrinsic line:

public final long incrementAndGet() {
        return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
}

What advantage this code has over the former? How does this new code work?

Upvotes: 5

Views: 822

Answers (3)

suranjan
suranjan

Reputation: 447

As discussed in link provided by Jim, in Java 8 incrementAndGet and other methods are taking advantage of hardware support for "lock, fetch and add" instruction.

Upvotes: 0

apangin
apangin

Reputation: 98284

unsafe.getAndAddLong is JVM intrinsic which is translated by JIT into an optimized instruction sequence. On x86 it is just a single CPU instruction LOCK XADD.

Upvotes: 5

Jim Garrison
Jim Garrison

Reputation: 86764

The reason is branch prediction on the loop. Under high contention the CAS loop fails often and the branch predictor starts to predict the execution path will stay in the loop, causing lots of pipeline flushing when the CAS eventually succeeds. Also this speeds up the loop when what you really want is a backoff when CAS fails, not a speedup.

See https://blogs.oracle.com/dave/entry/atomic_fetch_and_add_vs for a more detailed treatment.

Upvotes: 6

Related Questions