Получить доступ

Один поток в цикле читает обычное поле-флаг, другой его меняет, но цикл не завершается. Почему?

JuniorJVM и сборка мусора
Ещё спрашивают так:
  • Что делает volatile?
  • Что такое проблема видимости в многопоточности?
  • Чем volatile отличается от synchronized?
Коротко

Проблема видимости: без синхронизации нет гарантии, что поток увидит изменение, сделанное другим, — нужен volatile или синхронизация.

  • Компилятор и процессор вправе кэшировать значение и переупорядочивать операции
  • volatile даёт видимость и порядок (happens-before), но не атомарность count++

А ещё Для флага остановки volatile достаточно, для счётчика — нет

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Java Memory Model разрешает компилятору (в том числе JIT) и процессору оптимизации: держать значение поля в регистре или кэше ядра, переупорядочивать независимые операции. Для одного потока это незаметно, но другой поток может бесконечно читать старое значение. JIT вправе превратить while (!stop) {} в бесконечный цикл, прочитав stop один раз.

volatile на поле даёт две гарантии:

  • видимость — запись сразу видна всем потокам, чтение всегда берёт актуальное значение;
  • порядок — запись в volatile-поле «публикует» всё, что поток записал до неё: другой поток, прочитавший volatile, увидит и эти изменения (отношение happens-before).

Чего volatile не даёт — атомарности составных операций. count++ — это чтение, прибавление и запись; два потока всё равно потеряют обновление. Для этого нужны AtomicInteger или блокировка.

Типичное правильное применение volatile — флаг остановки, признак готовности, безопасная публикация неизменяемого объекта.

Пример

class Worker implements Runnable {
    private volatile boolean stopped;   // без volatile цикл может не завершиться

    public void run() {
        while (!stopped) { doWork(); }
    }
    public void stop() { stopped = true; }
}

Что хотят услышать

  • Причина: кэширование и переупорядочивание, нет гарантии видимости.
  • Решение: volatile или синхронизация.
  • Что даёт volatile (видимость, порядок) и чего не даёт (атомарность).

Частые ошибки

  • Считать, что изменение поля всегда сразу видно другим потокам.
  • Использовать volatile для счётчика и терять обновления.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓Без синхронизации нет гарантии видимости: читающий поток может не увидеть изменение — нужен volatile или синхронизация
  • ✗Изменение поля не успело записаться в память из-за задержки диска
  • ✗Поток с циклом имеет более высокий приоритет и блокирует запись
  • ✗Значение типа boolean нельзя менять из другого потока

Что спросят дальше

  • Почему volatile не годится для счётчика?
  • Какие ещё конструкции дают гарантию видимости?

Разбор темы

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем