Reggie1980
Reggie1980

Reputation:

Does AtomicBoolean not have a negate() method?

Does java.util.concurrent.atomic.AtomicBoolean not have a method that can atomically negate/invert the value? Can I do it another way? Am I missing something?

Upvotes: 24

Views: 4909

Answers (6)

XenoAmess
XenoAmess

Reputation: 375

If you are dealing with java 9 or later I suggest:

    /**
     * Flip the AtomicBoolean.
     * Sets the boolean value to false if it is true, and to true if it is false
     * with memory effects as specified by {@link java.lang.invoke.VarHandle#setVolatile}.
     *
     * @param atomicBoolean atomicBoolean
     * @return new boolean value of AtomicBoolean
     * @see AtomicInteger#accumulateAndGet(int x, IntBinaryOperator accumulatorFunction)
     * @since 9
     */
    public static final boolean flip(AtomicBoolean atomicBoolean) {
        boolean prev = atomicBoolean.get(), next = false;
        for (boolean haveNext = false; ; ) {
            if (!haveNext) {
                next = !prev;
            }
            if (atomicBoolean.weakCompareAndSetVolatile(prev, next)) {
                return next;
            }
            haveNext = (prev == (prev = atomicBoolean.get()));
        }
    }

Or if you want get it directly...

https://github.com/XenoAmess/commonx/blob/master/src/main/java/com/xenoamess/commonx/java/util/concurrent/atomic/AtomicBooleanUtilsx.java

Upvotes: 1

Leo
Leo

Reputation: 2199

You can emulate AtomicBoolean.negate() by using AtomicInteger.getAndIncrement() and considering even numbers as true and odd numbers as false. The actual value of the number should be ignored so you don't care about integer overflows.

Upvotes: 7

deamon
deamon

Reputation: 92539

The solution suggested in the book The CERT Oracle Secure Coding Standard for Java is the following:

import java.util.concurrent.atomic.AtomicBoolean;

final class Flag {
    private AtomicBoolean flag = new AtomicBoolean(true);

    public void toggle() {
        boolean temp;
        do {
            temp = flag.get();
        } while(!flag.compareAndSet(temp, !temp));
    }
}

Upvotes: 3

Seb T
Seb T

Reputation: 912

Using the AtomicBoolean#compareAndSet() method and a while loop you can implement a method to toggle the value of an AtomicBoolean in a thread-safe manner like this:

public static boolean negate(AtomicBoolean ab) {
    // get the oposite value
    boolean newVal = !ab.get();

    // try to set the new value if the current value is the oposite of the new value
    while (!ab.compareAndSet(!newVal, newVal)) {
        // if the value we try to set was already set in the mean-time
        // then toggle the new value and try again
        newVal = !newVal;
    }
    // return the value we finally could set
    return newVal;
}

Upvotes: 1

Joachim Sauer
Joachim Sauer

Reputation: 308209

My naive implementation would be this:

boolean v;
do {
  v=atomicBoolean.get();
} while(!atomicBoolean.compareAndSet(v, !v));

Upvotes: 15

Rob
Rob

Reputation: 221

Little old... but didn't really feel the answers were great.

Would have to totally disagree that this is not common or only useful in hardware. You may want a number of threads to toggle on a single variable with equal likelihood... I used the AtomicLong to make a fake boolean. This was adopted from a JMS MessageListener that I needed to respond a particular message half the time and another type the other half.

public class Mock {
    private static AtomicLong count = new AtomicLong(0);

    public boolean respond() {
        long currentCount = count.getAndIncrement();

        if (currentCount % 2 == 0) {
            return true;
        } else {
            return false;
        }
    }
}

Upvotes: 22

Related Questions