Відповіді:
Коли кілька потоків потрібно перевірити і змінити булеву форму. Наприклад:
if (!initialized) {
initialize();
initialized = true;
}
Це не є безпечним для потоків. Ви можете виправити це за допомогою AtomicBoolean
:
if (atomicInitialized.compareAndSet(false, true)) {
initialize();
}
true
коли initialize()
його не завершено. Отже, це працює лише в тому випадку, якщо інші теми не дбають про завершення initialize()
.
initialized
його просто використовують для того, щоб один і лише один потік викликав initialize()
метод. Очевидно, initialized
що правда не означає, що в цьому випадку ініціалізація точно закінчилася, тому, можливо, тут буде трохи інший термін. Знову ж таки, це залежить від того, для чого він використовується.
volatile boolean
було б як AtomicBoolean
?.
synchronized
блок, і в цьому випадку вам більше не потрібен AtomicBoolean
, а просто volatile boolean
. ( if(! this.initialized) { synchronized(this) { if(! this.initialized) { initialize(); this.initialized = true; } } }
забезпечить виклик лише одного потоку initialize
, і всі інші потоки чекають його, якщо initialized
це позначено volatile
.)
Ось замітки (з книги Брайана Геца ), які я зробив, які можуть вам допомогти
Класи AtomicXXX
забезпечити неблокуючу реалізацію порівняння та заміни
Користується технічною підтримкою (інструкція CMPXCHG для Intel) Коли через ваш код використовується багато потоків, що використовує цей атомний API паралельності, вони будуть масштабуватися набагато краще, ніж код, який використовує монітори / синхронізацію рівня об'єктів. Оскільки механізми синхронізації Java змушують код чекати, коли через ваші критичні розділи проходить безліч потоків, значна частина процесорного часу витрачається на управління самим механізмом синхронізації (очікування, повідомлення тощо). Оскільки новий API використовує апаратні конструкції рівня (атомні змінні) і чекає та блокує вільні алгоритми для впровадження безпеки потоку, набагато більше часу процесора витрачається на "виконання матеріалів", а не на управління синхронізацією.
вони не тільки пропонують кращу пропускну здатність, але й забезпечують більший опір проблемам життєдіяльності, таких як тупиковість та інверсія пріоритету.
Є дві основні причини, чому можна використовувати атомний бул. Спочатку його змінний, ви можете передати його як посилання та змінити значення, яке пов'язане, наприклад, із булевим.
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, ви повинні синхронізувати булеву змінну, яку ви використовуєте, оголосивши її мінливою або синхронізуючи навколо поля читання і запису.
AtomicBoolean
Клас дає логічне значення , яке ви можете оновити атомарному. Використовуйте його, коли у вас є кілька потоків, що мають доступ до булевої змінної.
Огляд java.util.concurrent.atomic пакет дає вам гарне високорівневе опис того , що класи в цьому пакеті і коли використовувати їх. Я також порекомендував би книгу « Конкурс Java на практиці » Брайана Геца.
Витяг з опису упаковки
Пакет java.util.concurrent.atomic Опис: Невеликий набір інструментаріїв класів, які підтримують безпечне програмування без заблокування потоків на окремих змінних. [...]
Специфікації цих методів дозволяють реалізаціям використовувати ефективні атомні інструкції на рівні машин, доступні для сучасних процесорів. [...]
Примірники класів AtomicBoolean, AtomicInteger, AtomicLong та AtomicReference кожен забезпечують доступ та оновлення до однієї змінної відповідного типу. [...]
Ефекти пам’яті для доступу та оновлень атома зазвичай відповідають правилам летючих речовин:
- get має на пам'яті ефекти читання мінливої змінної.
- Набір має ефекти на пам'ять написання (призначення) мінливої змінної.
- слабкий атомний зчитує та умовно пише змінну, впорядковується відносно інших операцій з пам'яттю на цій змінній, але в іншому випадку діє як звичайна операція з енергонезалежною пам'яттю.
- сравнениеAndSet та всі інші операції з читання та оновлення, такі як getAndIncrement, впливають на пам'ять як читання, так і запису змінних змінних.
volatile boolean
протиAtomicBoolean
: stackoverflow.com/questions/3786825 / ...