AtomicBoolean没有negate()方法吗?

时间:2009-08-10 15:37:12

标签: java multithreading concurrency

java.util.concurrent.atomic.AtomicBoolean没有可以原子地否定/反转值的方法吗?我可以用另一种方式吗?我错过了什么吗?

6 个答案:

答案 0 :(得分:14)

年纪稍大......但并不觉得答案很棒。

必须完全不同意这不常见或仅在硬件中有用。您可能需要多个线程在单个变量上切换,具有相同的可能性...我使用AtomicLong制作假布尔值。这是从JMS MessageListener中采用的,我需要在一半的时间内响应特定的消息而另一半的类型是另一半。

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;
        }
    }
}

答案 1 :(得分:12)

我天真的实施是这样的:

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

答案 2 :(得分:1)

书籍The CERT Oracle Secure Coding Standard for Java中建议的解决方案如下:

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));
    }
}

答案 3 :(得分:0)

使用AtomicBoolean#compareAndSet()方法和while循环,您可以实现一种方法,以线程安全的方式切换AtomicBoolean的值,如下所示:

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;
}

答案 4 :(得分:0)

您可以使用AtomicBoolean.negate()模拟AtomicInteger.getAndIncrement(),并将偶数视为true,将奇数视为false。 应该忽略该数字的实际值,因此您不必关心整数溢出。

答案 5 :(得分:0)

如果您使用的是Java 9或更高版本,我建议:

    /**
     * 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()));
        }
    }

或者如果您想直接获得它...

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