Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update an Atomic based on a condition?

How to update an AtomicInteger if its current value is less than the given value? The idea is:

AtomicInteger ai = new AtomicInteger(0);
...
ai.update(threadInt); // this call happens concurrently
...
// inside AtomicInteger atomic operation
synchronized {
    if (ai.currentvalue < threadInt)
        ai.currentvalue = threadInt;
}
like image 548
Stephan Rozinsky Avatar asked Apr 14 '15 11:04

Stephan Rozinsky


3 Answers

If you are using Java 8 you can use one of the new update methods in AtomicInteger, which you can pass a lambda expression. For example:

AtomicInteger ai = new AtomicInteger(0);

int threadInt = ...

// Update ai atomically, but only if the current value is less than threadInt
ai.updateAndGet(value -> value < threadInt ? threadInt : value);
like image 51
Jesper Avatar answered Nov 05 '22 06:11

Jesper


If you don't have Java 8, you can use a CAS-loop like this :

while (true) {
    int currentValue = ai.get();
    if (newValue > currentValue) {
        if (ai.compareAndSet(currentValue, newValue)) {
            break;
        }
    }
}
like image 20
Olivier Croisier Avatar answered Nov 05 '22 07:11

Olivier Croisier


If I didn't have Java 8, I would probably create a utility method, something like:

public static boolean setIfIncreases(AtomicInteger ai, int newValue) {
    int currentValue;
    do {
        currentValue = ai.get();
        if (currentValue >= newValue) {
            return false;
        } 
     } while (!ai.compareAndSet(currentValue, newValue));
     return true;
}

From the OP's code, it would then be invoked thus:

AtomicInteger ai = new AtomicInteger(0);

int threadInt = ...

// Update ai atomically, but only if the current value is less than threadInt
setIfIncreases(ai, threadInt);
like image 4
Mikko Östlund Avatar answered Nov 05 '22 06:11

Mikko Östlund