Модель памяти Java
Модель памяти Java описывает, как потоки языка программирования Java взаимодействуют через память. Вместе с описанием однопоточного выполнения кода модель памяти обеспечивает семантику языка программирования Java.
Первоначальная модель памяти Java, разработанная в 1995 году, была широко воспринята как неработающая. [ 1 ] предотвращение многих оптимизаций во время выполнения и отсутствие достаточно надежных гарантий безопасности кода. Он был обновлен через процесс сообщества Java как Запрос спецификации Java 133 (JSR-133), который вступил в силу еще в 2004 году для Tiger (Java 5.0) . [ 2 ] [ 3 ]
Контекст
[ редактировать ]Язык программирования и платформа Java предоставляют возможности потоков . Синхронизация между потоками, как известно, сложна для разработчиков; Эта трудность усугубляется тем, что приложения Java могут работать на широком спектре процессоров и операционных систем . Чтобы иметь возможность делать выводы о поведении программы, разработчики Java решили, что им необходимо четко определить возможное поведение всех программ Java.
На современных платформах код часто выполняется не в том порядке, в котором он был написан. Его порядок переупорядочивается компилятором, процессором и подсистемой памяти для достижения максимальной производительности. В многопроцессорных архитектурах отдельные процессоры могут иметь свои собственные локальные кэши, которые не синхронизированы с основной памятью. Как правило, нежелательно требовать, чтобы потоки оставались идеально синхронизированными друг с другом, поскольку это было бы слишком затратно с точки зрения производительности. Это означает, что в любой момент времени разные потоки могут видеть разные значения одних и тех же общих данных.
В однопоточной среде легко рассуждать о выполнении кода. Типичный подход требует, чтобы система реализовала последовательную семантику для отдельных потоков изолированно. При выполнении отдельного потока будет выглядеть так, как будто все действия, выполняемые этим потоком, происходят в том порядке, в котором они появляются в программе, даже если сами действия происходят не по порядку.
Если один поток выполняет свои инструкции не по порядку, то другой поток может увидеть тот факт, что эти инструкции были выполнены не по порядку, даже если это не повлияло на семантику первого потока. Например, рассмотрим два потока со следующими инструкциями, выполняемыми одновременно, где обе переменные x и y инициализируются значением 0:
Тема 1 | Тема 2 |
---|---|
х = 1; | интервал г1 = у; |
у = 2; | интервал г2 = х; |
Если переупорядочение не выполняется и чтение y в потоке 2 возвращает значение 2, то последующее чтение x должно возвращать значение 1, поскольку запись в x была выполнена до записи в y. Однако если две записи переупорядочены, то чтение y может вернуть значение 2, а чтение x может вернуть значение 0.
Модель памяти Java (JMM) определяет допустимое поведение многопоточных программ и, следовательно, описывает, когда такое переупорядочение возможно. Он накладывает ограничения времени выполнения на взаимоотношения между потоками и основной памятью для достижения согласованных и надежных приложений Java. Это позволяет рассуждать о выполнении кода в многопоточной среде даже с учетом оптимизации, выполняемой динамическим компилятором, процессором(ами) и кэшем.
Модель памяти
[ редактировать ]Для выполнения одного потока правила просты. Спецификация языка Java требует, чтобы виртуальная машина Java наблюдала внутрипотоковую семантику как если бы она была последовательной. Среда выполнения (которая в данном случае обычно относится к динамическому компилятору, процессору и подсистеме памяти) может вводить любые полезные оптимизации выполнения, при условии, что результат изолированного потока гарантированно будет точно таким же, как и его результат. было бы, если бы все операторы выполнялись в том порядке, в котором они встречались в программе (также называемый порядком программы). [ 4 ]
Основное предостережение заключается в том, что последовательная семантика «как если бы» не препятствует разным потокам иметь разные представления данных. Модель памяти дает четкое представление о том, какие значения разрешено возвращать при чтении данных. Основные правила подразумевают, что отдельные действия могут быть переупорядочены, пока не нарушается последовательная семантика потока как если бы, а действия, предполагающие связь между потоками, такие как получение или снятие блокировки , гарантируют, что действия, которые происходят до них, их видят другие потоки, которые видят их эффекты. Например, все, что происходит до снятия блокировки, будет восприниматься как упорядоченное до и видимое для всего, что происходит после последующего получения той же самой блокировки. [ 5 ]
Математически существует частичный порядок , называемый порядком «происходит до» всех действий, выполняемых программой. Порядок «происходит до» включает в себя порядок программы; если одно действие происходит раньше другого в порядке программы, оно произойдет раньше другого в порядке «происходит до» . Кроме того, выпуски и последующие захваты блокировок образуют ребра в графе «случилось до». Чтению разрешено возвращать значение записи, если эта запись является последней записью в эту переменную перед чтением по некоторому пути в порядке «до того, как происходит» , или если запись не упорядочена по отношению к этому чтению в порядке «происходит». перед заказом.
Влияние
[ редактировать ]Модель памяти Java была первой попыткой предоставить комплексную модель памяти для популярного языка программирования. [ 6 ] Это было оправдано растущей распространенностью параллельных и параллельных систем, а также необходимостью предоставить инструменты и технологии с четкой семантикой для таких систем. С тех пор потребность в модели памяти получила более широкое признание, и аналогичная семантика была предоставлена для таких языков, как C++ . [ 7 ]
См. также
[ редактировать ]Ссылки
[ редактировать ]- ^ Пью, Уильям (2000). «Модель памяти Java фатально ошибочна» (PDF) . Параллелизм: практика и опыт . 12 (6): 445–455. doi : 10.1002/1096-9128(200005)12:6<445::AID-CPE484>3.0.CO;2-A . Проверено 15 июля 2021 г.
- ^ Гетц, Брайан (24 февраля 2004 г.). «Исправление модели памяти Java, часть 2» (PDF) . ИБМ . Проверено 18 октября 2010 г.
- ^ Джереми Мэнсон и Брайан Гетц (февраль 2004 г.). «Часто задаваемые вопросы по JSR 133 (модель памяти Java)» . Проверено 18 октября 2010 г.
Модель памяти Java описывает, какое поведение допустимо в многопоточном коде и как потоки могут взаимодействовать через память. Он описывает взаимосвязь между переменными в программе и низкоуровневыми деталями их хранения и извлечения из памяти или регистров в реальной компьютерной системе. Это делается таким образом, что его можно правильно реализовать с использованием широкого спектра аппаратного обеспечения и множества оптимизаций компилятора.
- ^ Мэнсон, Джереми. «Часто задаваемые вопросы по JSR-133» .
- ^ «JLS случается до заказа» .
- ^ Гетц, Брайан (24 февраля 2004 г.). «Исправление модели памяти Java, часть 1» (PDF) . ИБМ . Проверено 17 февраля 2008 г.
- ^ Бём, Ганс. «Модель потоков и памяти для C++» . Проверено 8 августа 2014 г.
Внешние ссылки
[ редактировать ]- Теория и практика Java: исправление модели памяти Java, часть 1 — статья, описывающая проблемы с исходной моделью памяти Java.
- Теория и практика Java: исправление модели памяти Java, часть 2. Объясняет изменения, внесенные JSR 133 в модель памяти Java.
- Прагматика модели памяти Java (расшифровка)
- Ссылки на модель памяти Java
- Внутренняя структура Java
- Веб-страница JSR-133
- Часто задаваемые вопросы по JSR-133
- Руководство по реализации JSR-133