2016-03-07 4 views
1

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

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) из другого потока?

ответ

2

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

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

+0

Я не уверен. Если есть несколько читателей и _one_ писатель, то, возможно, _volatile_ гарантии достаточно.Но в тот момент, когда есть несколько авторов, я не уверен, что использование _volatile_ гарантировано. –

+2

Посмотрите на источник AtomicBoolean - это в основном volatile boolean в объекте, если вы не используете методы compareAndSet. Множество авторов не проблема, в любом случае. –

+0

Согласно [this] (http://tutorials.jenkov.com/java-concurrency/volatile.html) (не уверен, насколько это точно), видимо, это нормально, если есть несколько авторов, если новые письменные значения не зависит от предыдущего значения, но как только вам нужно проверить предыдущее значение, установите новый, основанный на предыдущем, а затем «volatile» недостаточно. –

0

Да. От Javadoc от AtomicBoolean:

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

Это означает, что любое обновление AtomicBoolean является неделимой. Поэтому я бы счел такое использование AtomicBooleanпотоковым сейфом.

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

private final AtomicBoolean running;

+2

Любое обновление любой переменной 'boolean' неделимо. В классах «AtomicXxxxxxx» вы покупаете две вещи: (a) они дают вам «volatile» -подобный доступ к первообразному значению и (b) они дают вам блокирующие реализации 'getAndSet()', 'compareAndSet()' , 'incrementAndGet()' и т. д. –

1

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

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

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

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

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

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

+0

Вы говорите, если я «изменяю какую-то переменную» ... Вы имеете в виду, если я изменю ее внутри синхронизированного блока для случая 1 и сразу после блока if, который использует AtomicBoolean/volatile в случае 2? –

+0

@JackmeriusTacktheritrix добавил пример – AdamSkywalker

+0

Правильно, приращение 'x' не является потокобезопасным. В фактическом коде нет никаких небезопасных обновлений, которые происходят после if-блока, поэтому я думаю, что я должен быть в порядке. –

 Смежные вопросы

  • Нет связанных вопросов^_^