Использование 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;