Reputation:
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
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...
Upvotes: 1
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
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
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
Reputation: 308209
My naive implementation would be this:
boolean v;
do {
v=atomicBoolean.get();
} while(!atomicBoolean.compareAndSet(v, !v));
Upvotes: 15
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