Разве у AtomicBoolean нет метода negate ()? - PullRequest
14 голосов
/ 10 августа 2009

Разве у java.util.concurrent.atomic.AtomicBoolean нет метода, который может атомарно отрицать / инвертировать значение? Могу ли я сделать это по-другому? Я что-то упустил?

Ответы [ 6 ]

15 голосов
/ 28 сентября 2012

Старенький ... но на самом деле не чувствовал, что ответы были хорошими.

Пришлось бы полностью не согласиться с тем, что это не распространено или полезно только в аппаратном обеспечении. Возможно, вы захотите, чтобы несколько потоков переключались на одну переменную с равной вероятностью ... Я использовал 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;
        }
    }
}
13 голосов
/ 10 августа 2009

Моя наивная реализация была бы такой:

boolean v;
do {
  v=atomicBoolean.get();
} while(!atomicBoolean.compareAndSet(v, !v));
1 голос
/ 01 декабря 2017

Решение, предложенное в книге Стандарт CERT Oracle Secure Coding для 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));
    }
}
0 голосов
/ 06 июня 2019

Если вы имеете дело с 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

0 голосов
/ 16 апреля 2018

Вы можете эмулировать AtomicBoolean.negate(), используя AtomicInteger.getAndIncrement() и считая четные числа как true и нечетные числа как false. Фактическое значение числа следует игнорировать, чтобы не беспокоиться о целочисленных переполнениях.

0 голосов
/ 15 августа 2017

Используя метод 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...