volatile обеспечивает видимость изменений переменной для разных потоков и запрещает компилятору и JVM переупорядочивать инструкции, связанные с этой переменной. Это гарантирует, что при чтении volatile переменной поток увидит самое последнее записанное значение. Однако volatile не гарантирует атомарность составных операций (например, инкремента).
Атомарные классы из пакета java.util.concurrent.atomic (например, AtomicInteger, AtomicLong, AtomicReference) используют низкоуровневые атомарные операции, такие как Compare-And-Swap (CAS), которые выполняются на аппаратном уровне. Они гарантируют, что операции чтения-изменения-записи выполняются атомарно, без необходимости явной синхронизации с использованием synchronized.
Сравнение:
| Признак | volatile | Атомарные переменные (AtomicInteger и т.д.) |
|---|---|---|
| Атомарность | Не гарантирует атомарность составных операций. | Гарантируют атомарность операций (CAS). |
| Видимость | Гарантирует видимость изменений для других потоков. | Гарантируют видимость (побочный эффект CAS). |
| Использование | Для обеспечения видимости простого чтения/записи. | Для атомарных операций типа инкремента, CAS. |
| Накладные расходы | Меньше накладных расходов, чем у synchronized. | Обычно меньше накладных расходов, чем у synchronized в условиях низкой конкуренции. |
Пример использования volatile:
java
Пример использования AtomicInteger:
java