Модель памяти Java (Java Memory Model, JMM) определяет, как потоки видят изменения, вносимые другими потоками. Она гарантирует согласованность данных в параллельных программах, определяя правила видимости и порядка выполнения операций read/write.
Основные понятия JMM:
Ключевые механизмы и ключевые слова для управления видимостью и порядком:
synchronized: Обеспечивает взаимное исключение (одновременный доступ только одного потока) и гарантирует видимость изменений до и после блока synchronized. Имеет семантику acquire-release в терминах JMM.volatile: Гарантирует видимость изменений переменной для всех потоков. Чтение volatile переменной всегда читает последнее записанное значение, а запись гарантирует, что все предыдущие записи станут видимыми. Запрещает reordering (переупорядочивание) операций чтения/записи вокруг volatile переменной.final: Гарантирует, что если объект виден другим потокам после завершения конструктора, то все final поля этого объекта инициализированы и видны корректно.Используются также Lock (например, ReentrantLock), которые реализуют более гибкую синхронизацию, но также основаны на принципах JMM. Пакет java.util.concurrent.atomic предоставляет классы для атомарных операций без явной блокировки на уровне потоков.
Связь между потоками и памятью в JMM описывается отношениями "happens-before". Если операция А "happens-before" операция B, то все побочные эффекты операции А становятся видимыми для операции B. Некоторые из этих отношений устанавливаются неявно:
synchronized блока) "happens-before" последующее захват того же монитора.volatile: Запись volatile переменной "happens-before" последующее чтение этой же переменной.Thread.start() "happens-before" первая операция в новом потоке.Thread.join() соответствующего потока.Понимание JMM необходимо для написания корректных, потокобезопасных многопоточных программ. Использование соответствующих механизмов синхронизации и понимание их семантики в рамках JMM позволяет избежать проблем с видимостью данных и некорректным порядком выполнения операций.