Сначала ответь вслух
Скажи ответ вслух хотя бы пару минут, потом открой эталон и сравни. Эталон открыт всем и не требует входа.
Показать ответ
Эталонный ответ
Без синхронизации поток может не увидеть запись другого потока: значение осталось в регистре, или JIT вынес чтение поля из цикла. Запись в volatile-поле происходит-раньше (happens-before) каждого последующего чтения этого поля, поэтому читатель увидит и само значение, и всё, что поток записал до него.
class Worker {
private volatile boolean running = true;
void stop() { running = false; }
void loop() {
while (running) {
// без volatile цикл может не увидеть stop()
}
}
}count++ раскладывается на три действия: прочитать, прибавить, записать. Два потока могут прочитать 5 и оба записать 6. Для счётчиков нужны AtomicInteger, LongAdder или synchronized.
Как у тебя получилось?
Уточняющие вопросы
Так обычно копают глубже. Раскрой строку, когда ответишь вслух.
Уточнение 1-го уровня: Когда volatile достаточно?
Ответ уровня Middle
Когда пишет один поток, а остальные читают: флаг остановки, публикация ссылки на неизменяемый объект, состояние, которое меняется одной записью.
Уточнение 2-го уровня: Зачем volatile в double-checked locking?
Ответ уровня Senior
Без него другой поток может увидеть ненулевую ссылку на объект, конструктор которого ещё не закончил запись полей: запись ссылки и полей могут переставиться.
Уточнение 3-го уровня: Чем LongAdder лучше AtomicLong под нагрузкой?
Ответ уровня Senior
AtomicLong — одна ячейка, и при высокой конкуренции потоки крутятся на неудачных CAS. LongAdder раскладывает счёт по ячейкам и складывает их в sum(); зато sum() не атомарный снимок.
Типичные ошибки
- Считать, что volatile делает составные операции атомарными.
- Ставить volatile на ссылку и ждать потокобезопасности от изменяемого объекта по ней.
Первоисточники
Быстрые задания по теме
boolean flag;
void stop() { flag = true; }
void run() { while (!flag) { } }Проверь себя
Задание 1 из 1Поток A пишет в поле flag, поток B читает его в цикле. Что нужно, чтобы B гарантированно увидел запись?