Как я могу использовать AtomicBoolean и для чего этот класс?
Когда мне нужно использовать AtomicBoolean в Java?
Ответ 1
Когда несколько потоков должны проверять и изменять логическое значение. Например:
if (!initialized) {
initialize();
initialized = true;
}
Это не потокобезопасно. Вы можете исправить это, используя AtomicBoolean
:
if (atomicInitialized.compareAndSet(false, true)) {
initialize();
}
Ответ 2
Вот заметки (из книги Брайана Гетца), которые я сделал, которые могут быть вам полезны
Классы AtomicXXX
-
обеспечить неблокирующую реализацию Compare-And-Swap
-
Использует аппаратную поддержку (инструкция CMPXCHG для Intel). Когда через ваш код выполняется множество потоков, использующих этот API-интерфейс атомарного параллелизма, они будут масштабироваться намного лучше, чем код, использующий мониторы/синхронизацию на уровне объектов. Поскольку механизмы синхронизации Java заставляют код ждать, когда в критических секциях выполняется множество потоков, значительное количество процессорного времени затрачивается на управление самим механизмом синхронизации (ожидание, уведомление и т.д.). Поскольку новый API использует конструкции аппаратного уровня (атомарные переменные) и алгоритмы ожидания и блокировки без блокировки для реализации безопасности потоков, гораздо больше процессорного времени тратится на "выполнение задач", а не на управление синхронизацией.
-
они не только обеспечивают лучшую пропускную способность, но и обеспечивают большую устойчивость к таким проблемам, как тупик и инверсия приоритетов.
Ответ 3
Есть две основные причины, по которым вы можете использовать атомный булев. Сначала его можно изменить, вы можете передать его как ссылку и изменить значение, которое связано, например, с булевым.
public final class MyThreadSafeClass{
private AtomicBoolean myBoolean = new AtomicBoolean(false);
private SomeThreadSafeObject someObject = new SomeThreadSafeObject();
public boolean doSomething(){
someObject.doSomeWork(myBoolean);
return myBoolean.get(); //will return true
}
}
и в классе someObject
public final class SomeThreadSafeObject{
public void doSomeWork(AtomicBoolean b){
b.set(true);
}
}
Более того, несмотря на то, что его поток безопасен и может указывать разработчикам, поддерживающим класс, ожидается, что эта переменная будет изменена и прочитана из нескольких потоков. Если вы не используете AtomicBoolean, вы должны синхронизировать логическую переменную, которую используете, объявив ее изменчивой или синхронизированной вокруг чтения и записи поля.
Ответ 4
Класс AtomicBoolean
дает вам логическое значение, которое вы можете обновлять атомарно. Используйте его, когда у нескольких потоков есть доступ к логической переменной.
Обзор пакета java.util.concurrent.atomic дает хорошее общее описание того, что делают классы в этом пакете и когда их использовать. Я бы также порекомендовал книгу Брайана Гетца о параллельности Java на практике.
Ответ 5
Выдержка из описания пакета
Пакет java.util.concurrent.atomic description: Небольшой инструментарий классов, которые поддерживают поточно-ориентированное программирование без блокировок для отдельных переменных. [...]
Спецификации этих методов позволяют реализациям использовать эффективные атомарные инструкции машинного уровня, доступные на современных процессорах. [...]
Каждый из экземпляров классов AtomicBoolean, AtomicInteger, AtomicLong и AtomicReference каждый обеспечивает доступ и обновления к одной переменной соответствующего типа. [...]
Эффекты памяти для доступа и обновлений атомики обычно следуют правилам для летучих:
- get имеет эффект памяти чтения изменчивой переменной.
- set имеет эффект памяти записи (присваивания) переменной переменной.
- weakCompareAndSet атомарно читает и условно записывает переменную, упорядочивается по отношению к другим операциям памяти с этой переменной, но в остальном действует как обычная операция энергонезависимой памяти.
- compareAndSet и все другие операции чтения и обновления, такие как getAndIncrement, влияют на память как чтения, так и записи изменяемых переменных.