Использование AtomicBoolean вместо синхронизированных блоков

Скажем, у меня есть класс с 2 переменными экземпляра и следующими методами (упрощенно для этого вопроса):

private final Object lock = new Object();
private boolean running;

public MyClass() {
    synchronized(lock) {
        running = false;
    }
}
public void methodA() {
    synchronized(lock) {
        running = true;
    }
}
public void methodB() {
    synchronized(lock) {
        if (!running) {
            return;
        }
    }
}

Я смотрел на этот код, и после прочтения о AtomicBooleanЯ подумал, что здесь можно подойти, особенно после того, как MyClass конструктор и methodA, Я не был слишком уверен в methodB хоть.

Предполагая, что эти методы могут быть вызваны несколькими потоками, будет ли следующий потокобезопасным?

private AtomicBoolean running;

public MyClass() {
    running = new AtomicBoolean(false);
}
public void methodA() {
    running.set(true);
}
public void methodB() {
    if (!running.get()) {
        return;
    }
}

Будет running.get() гарантированно увидеть обновление через running.set(true) или же running.set(false) из другого потока?

3 ответа

Решение

В вашем примере простой volatile boolean было бы достаточно, так как вы, кажется, делаете только атомарные операции. AtomicBoolean полезен, если вам нужны такие методы, как compareAndSet,

Так что в ответ на ваш вопрос, да, при использовании volatile boolean или AtomicBooleanдругие потоки увидят обновления переменной.

Вообще говоря, эти кодовые блоки не равны для methodBпотому что читая volatile переменная не создает порядок синхронизации.

Представь, что у тебя есть какое-то другое поле int x = 42 в вашем классе это обновляется в methodB:

public void methodB() {
    if (!running.get()) {
        return;
    }
    if (x < 50) x++; // just example
}

Тогда у вас есть несколько потоков, которые вызывают methodB:

  • при использовании синхронизированного ключевого слова обновления являются безопасными и видимыми для всех потоков.
  • при использовании AtomicBoolean/volatile видимость нарушена

Если такого случая с обновлениями переменных не существует, и задача состоит только в том, чтобы гарантировать видимость между methodA - последовательностью methodB, то все в порядке - для этого достаточно AtomicBoolean.

Да. От Javadoc AtomicBoolean:

Значение {@code boolean}, которое может быть обновлено атомарно.

Это означает, что любое обновление AtomicBoolean неделим. Итак, я бы рассмотрел такое использование AtomicBoolean быть потокобезопасным.

Вы все еще должны рассмотреть вопрос о том, чтобы сделать заявление AtomicBoolean окончательный:

private final AtomicBoolean running;

Другие вопросы по тегам