Ответ
Ключевое слово volatile гарантирует две основные вещи в многопоточном контексте:
- Видимость (Visibility): Любое изменение значения
volatile-переменной, сделанное одним потоком, немедленно становится видимым для всех других потоков. Безvolatileизменения могут оставаться в кэше процессора потока и не быть видны другим. - Запрет переупорядочивания (Prevention of Reordering): Операции чтения и записи
volatile-переменной создают барьеры памяти. Это запрещает компилятору и процессору переставлять эти операции с другими операциями чтения/записи памяти, что сохраняет порядок, ожидаемый программистом.
Пример использования (флаг остановки):
public class WorkerThread implements Runnable {
private volatile boolean running = true; // Гарантирует, что поток B увидит изменение из потока A
public void run() {
while (running) { // Чтение всегда актуального значения
// выполнение работы
}
}
public void stop() {
running = false; // Запись видна всем потокам
}
}
Чего volatile НЕ гарантирует:
- Атомарность составных операций. Операция
count++(чтение-изменение-запись) не является атомарной, даже еслиcountобъявлен какvolatile. Для атомарных операций используйтеAtomicIntegerили синхронизацию. - Взаимное исключение (mutual exclusion).
volatileне заменяетsynchronized.
Типичные сценарии: простые флаги состояния, однократная инициализация (шаблон Singleton с Double-Checked Locking).