Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any functional difference between AtomicInteger.updateAndGet() and AtomicInteger.accumulateAndGet()?

Is there any scenario in which AtomicInteger.accumulateAndGet() can't be replaced with AtomicInteger.updateAndGet(), or is it just a convenience for method references?

Here's a simple example where I don't see any functional difference:

AtomicInteger i = new AtomicInteger();
i.accumulateAndGet(5, Math::max);
i.updateAndGet(x -> Math.max(x, 5));

Obviously, the same goes for getAndUpdate() and getAndAccumulate().

like image 848
shmosel Avatar asked Mar 15 '16 21:03

shmosel


1 Answers

When in doubt, you may look into implementation:

public final int accumulateAndGet(int x,
                                  IntBinaryOperator accumulatorFunction) {
    int prev, next;
    do {
        prev = get();
        next = accumulatorFunction.applyAsInt(prev, x);
    } while (!compareAndSet(prev, next));
    return next;
}

public final int updateAndGet(IntUnaryOperator updateFunction) {
    int prev, next;
    do {
        prev = get();
        next = updateFunction.applyAsInt(prev);
    } while (!compareAndSet(prev, next));
    return next;
}

They differ only in single line and obviously accumulateAndGet could be expressed easily via updateAndGet:

public final int accumulateAndGet(int x,
                                  IntBinaryOperator accumulatorFunction) {
    return updateAndGet(prev -> accumulatorFunction.applyAsInt(prev, x));
}

So updateAndGet is somewhat more basic operation and accumulateAndGet is a useful shortcut. Such shortcut might be especially helpful if your x is not effectively final:

int nextValue = 5;
if(something) nextValue = 6;
i.accumulateAndGet(nextValue, Math::max);
// i.updateAndGet(prev -> Math.max(prev, nextValue)); -- will not work
like image 111
Tagir Valeev Avatar answered Oct 03 '22 05:10

Tagir Valeev