Given an AtomicLong
object, what is the right way to decrement the value by a delta?
Option 1
AtomicLong count = new AtomicLong(0L); public void decrementCount(long decrementBy) { count.getAndUpdate(l->count.get() - decrementBy); }
Option 2
AtomicLong count = new AtomicLong(0L); public void decrementCount(long decrementBy) { count.getAndAdd(-decrementBy); }
While both give the desired result, I want to understand under what circumstance will they not represent the desired behavior i.e to decrement a long value atomically? (One drawback of the second approach for example could be the negative sign causing some bit overflow but I am not sure if that’s true)
Advertisement
Answer
count.getAndUpdate(l->count.get() - decrementBy);
This doesn’t work atomically. getAndUpdate
works roughly like this:
long getAndUpdate(LongUnaryOperator op) { long current; long newValue; do { current = this.get(); newValue = op.apply(current); while (!compareAndSet(current, newValue)); return current; }
By re-reading count.get()
inside the lambda, you’re reading the value of the AtomicLong
then, which might be different to the value of current
that it was passed, if some other thread updated the AtomicLong
in between; you’d then update based on the updated value, not current
.
Use the value you are passed in l
:
count.getAndUpdate(l->l - decrementBy);
But getAndAdd(-decrementBy)
is easier.