Когда следует использовать ключевое слово `volatile` в Java?

«Когда следует использовать ключевое слово `volatile` в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Модификатор volatile используется для переменных, к которым обращаются из нескольких потоков. Он гарантирует видимость изменений и запрещает переупорядочивание операций с этой переменной, но не обеспечивает атомарность составных операций.

Используйте volatile в следующих случаях:

  1. Флаги состояния для управления потоками. Простой и эффективный способ остановки потока.

    public class WorkerThread {
        private volatile boolean running = true;
        public void run() {
            while (running) { /* выполняем работу */ }
        }
        public void stop() { running = false; } // Изменение видно всем потокам
    }
  2. Публикация неизменяемых (immutable) объектов. Если объект полностью сконструирован и не будет меняться, ссылку на него можно безопасно опубликовать через volatile поле.

    public class Publisher {
        private volatile ImmutableConfig config;
        public void updateConfig(ImmutableConfig newConfig) {
            this.config = newConfig; // Безопасная публикация
        }
    }
  3. Одиночные операции записи. Когда переменная записывается одним потоком, а читается многими, и операция записи атомарна сама по себе (например, присваивание int, long, reference).

Когда volatile НЕ подходит:

  • Для операций типа check-then-act (проверить, затем изменить).
  • Для составных операций, таких как инкремент (i++).

В этих случаях требуются synchronized, Lock или атомарные классы (AtomicInteger, AtomicReference).