volatile — это модификатор переменной, который гарантирует видимость изменений этой переменной всеми потоками. Если переменная объявлена как volatile, то ее чтение и запись идут непосредственно из основной памяти, минуя локальные кэш-памяти потоков. Это предотвращает кеширование значений локально в потоке.
synchronized — это ключевое слово, которое обеспечивает не только видимость, но и взаимное исключение (mutual exclusion): только один поток может выполнять синхронизированный блок в один момент времени для одного объекта.
Использовать volatile переменные следует для простых флагов и счетчиков, если:
Пример использования volatile:
class Flag { private volatile boolean running = true; public void stop() { running = false; } public void loop() { while (running) { // ... } } }
Можно ли использовать volatile для обеспечения атомарности инкремента переменной?
Ответ:
Нет, volatile не обеспечивает атомарность операций. Например, counter++ не является атомарным даже если counter объявлен как volatile, потому что операция включает чтение, изменение и запись (несколько действий), которые могут быть прерваны другим потоком. Атомарность обеспечивается с помощью synchronized или классов из пакета java.util.concurrent.atomic.
Пример:
class Counter { private volatile int count = 0; public void increment() { count++; // НЕ атомарная операция! } }
История
В проекте онлайн-магазина флаг завершения потока обработки заказов был реализован без volatile. В результате один из потоков "залипал" в бесконечном цикле, т.к. не видел изменения переменной, сделанного из другого потока. Диагностика заняла несколько дней.
История
В финансовой системе разработчик использовал volatile int для счетчика операций. В пиковых нагрузках количество операций начинало "теряться". Причина — потеря атомарности при сложных операциях инкремента.
История
Разработчики перепутали volatile и synchronized, пытаясь использовать volatile для обеспечения взаимного исключения доступа к критическим секциям, что привело к data race и трудноуловимым багам в многопоточном приложении.