Ответ
Ключевое слово volatile в Java гарантирует видимость изменений переменной для всех потоков и запрещает реордеринг операций с ней, обеспечивая слабую форму синхронизации.
Что оно гарантирует?
- Видимость (Memory Visibility): Когда один поток записывает значение в
volatile-переменную, это изменение немедленно становится видимым для всех других потоков. Безvolatileизменение может остаться в кэше процессора и быть невидимым для других потоков. - Запрет реордеринга: Операции чтения/записи
volatile-переменной не могут быть переупорядочены компилятором или процессором относительно других операций, что создаёт точки happens-before в модели памяти Java.
Пример использования (флаг завершения):
class WorkerThread implements Runnable {
private volatile boolean running = true; // Критично — volatile!
public void run() {
while (running) { // Поток увидит изменение из main-потока
// Работа...
}
}
public void stop() {
running = false; // Сигнал на остановку
}
}
Важные ограничения и best practices:
- НЕ атомарность сложных операций: Операции вроде
count++(чтение-изменение-запись) не атомарны, даже еслиcountобъявлен какvolatile. Для таких случаев используйтеAtomicInteger. - Когда применять: Идеально для простых флагов состояния (
boolean running) или переменных, записываемых одним потоком и читаемых многими. - Чего не хватает:
volatileне обеспечивает взаимное исключение (mutual exclusion). Если несколько потоков могут изменять переменную, требуетсяsynchronizedили атомарные классы (java.util.concurrent.atomic).
Итог: volatile — это инструмент для управления видимостью, а не для обеспечения атомарности составных действий.