Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AtomicInteger incrementAndGet atomicity

AtomicInteger.incrementAndGet() is atomic according to the documentation.However, in its source code below, what if another thread interleaves just before "return next"? "Next" will be incorrect then?

public final long incrementAndGet() {
    for (;;) {
        long current = get();
        long next = current + 1;
        if (compareAndSet(current, next))
          return next;
    }
}
like image 600
TommyQ Avatar asked Mar 31 '14 07:03

TommyQ


2 Answers

If another thread interleaved then it would also successfully add one to the value.

Atomicity guarantees that your increment happens and that if two threads attempt an increment then eventually two threads will succeed (and increment by two). It does not guarantee anything about any future value.

In your scenario it would seem like the following code:

public final long incrementAndGet() {
    for (;;) {
        long current = get();
        long next = current + 1;
        if (compareAndSet(current, next)) {
            // Other thread.
            for (;;) {
                long current2 = get();
                long next2 = current2 + 1;
                if (compareAndSet(current2, next2)) {
                    return next2;
                }
            }
            return next;
        }
    }
}

i.e. each thread gets it's own incremented value.

like image 150
OldCurmudgeon Avatar answered Sep 21 '22 23:09

OldCurmudgeon


The value is incremented with every call correctly, so the only thing it could affect is the return value.

The semantics of the function are that it doesn't return the current value of the integer, but the value to which calling incrementAndGet() increased the integer (the updated value).

Let me give you an example:

public MyClass {
    private AtomicInteger counter;

    public int getNextUniqueIndex() {
        return counter.getAndIncrement();
    }
}

Now if you call getNextUniqueIndex() it will always return a unique value regardless of the calling thread or thread interleaving. That is because the value of next returned from the implementation of incrementAndGet() refers to the value updated by this call of incrementAndGet().

like image 28
Mifeet Avatar answered Sep 21 '22 23:09

Mifeet