Что дает термин memory model в Java и почему он появился
Что проверяют
Понимаете ли вы, что многопоточная программа выполняется не в том порядке, в каком написана, и что гарантии видимости даёт спецификация, а не здравый смысл. Вопрос отсекает тех, кто знает слова volatile и synchronized, но не знает, какую задачу они решают.
Как отвечать
Модель памяти Java это часть спецификации языка, описывающая, какие значения имеет право увидеть чтение переменной, когда с ней работают несколько потоков. Нужна она потому, что и компилятор, и JIT, и сам процессор переставляют операции, держат значения в регистрах и кэшах: код, корректный в одном потоке, в многопоточной программе читает устаревшее значение или вовсе невозможную комбинацию.
Центральное понятие это отношение happens-before: если действие A happens-before действия B, то результат A гарантированно виден B. Рёбра дают:
- выход из блока
synchronizedи последующий вход по тому же монитору; - запись в поле
volatileи последующее чтение того же поля; - запуск потока и всё, что было до него, а также завершение потока и
join; - запись поля
finalв конструкторе, если ссылка на объект не утекла наружу до его завершения.
Без такой пары гарантий нет, и программа с гонкой данных корректной не считается. В Java 5 модель переписали (JSR 133), до этого volatile и final нужных гарантий не давали.
private volatile boolean running = true;
// без volatile чтение поля поднимется из цикла и он будет крутиться вечно
while (running) { doWork(); }Где спотыкаются
Путают видимость с атомарностью. volatile гарантирует, что запись увидят, но count++ остаётся чтением, инкрементом и записью, и нужен synchronized либо AtomicInteger.
Второе: считают, что синхронизировать надо только запись. Чтение без синхронизации ничего не гарантирует, потому что happens-before возникает на паре операций, а не у одной стороны.
Третье: объясняют всё кэшем процессора, забыв про переупорядочивание компилятором, и ищут гонку под отладчиком. Там оптимизации не применяются, баг не воспроизводится, и его объявляют плавающим.