Вставка инструкций Fence с помощью JVM/JIT

Модель памяти Java дает гарантию DRF (свобода гонки данных), что означает, что программа, свободная от гонки данных, при выполнении в модели расслабленной памяти Java будет давать то же поведение, что и при последовательном последовательном выполнении. У меня есть следующий вопрос: а) Учитывая гоночную программу, делает ли компилятор (точнее, любую реализацию jvm) анализ набора задержек/анализ выхода потока и т. д., чтобы узнать инструкции забора, которые необходимо вставить, чтобы сделать его гонкой. бесплатно? или JIT делает это в зависимости от того, где он выполняется?

б) Если это делает компилятор (в данном случае jvm), почему мы не можем просто написать гоночную программу, потому что компилятор все равно преобразует ее в программу без гонок? И если компилятор каким-либо образом собирается это сделать (сделать его свободным от гонок путем вставки забора), как можно писать колоритные программы (намеренно), например, некоторые реализации параллельных структур данных в java?

c) Или третья возможность, что jvm сама по себе не преобразует расовую программу в программу, свободную от расы, но существует другой анализ, который может сделать это за нас. Так ли это?


person chinu    schedule 12.07.2011    source источник


Ответы (1)


Учитывая гоночную программу, выполняет ли компилятор (точнее, любую реализацию jvm) анализ набора задержек/анализ выхода потока и т. д., чтобы узнать инструкции забора, которые необходимо вставить, чтобы сделать его свободным от гонок? или JIT делает это в зависимости от того, где он выполняется?

Инструкции ограничения памяти специфичны для набора инструкций архитектуры. Они не являются эквивалентными инструкциями в наборе инструкций JVM. Таким образом, именно JVM/JIT фактически выдает процессору инструкции ограждения.

Если это делает компилятор (в данном случае jvm), почему мы не можем просто написать гоночную программу, потому что компилятор все равно преобразует ее в программу без гонок? И если компилятор каким-либо образом собирается это сделать (сделать его свободным от гонок путем вставки забора), как можно писать колоритные программы (намеренно), например, некоторые реализации параллельных структур данных в java?

Компилятор только гарантирует, что при генерации байтового кода все действия, выполняемые над переменными в JVM, подчиняются правилам, указанным в модели памяти Java. В частности, в области оптимизации компилятор может оптимизировать любой набор инструкций, если это не влияет на отношения «происходит до», которые должны существовать между действиями, или порядок синхронизации между действиями. Например, компилятор не будет реорганизовывать операции чтения и записи для volatile-переменных. Это также гарантирует, что отношения «происходит до» не нарушаются при входе или выходе из защищенных (синхронизированных) областей кода.

Таким образом, утверждение, что компилятор преобразует «гоночную» программу в программу без гонок, неверно. На самом деле программа, которая считается свободной от гонок (но не в соответствии с моделью памяти Java), может стать «гоночной» после оптимизации.

Параллельные реализации структур данных в Java полагаются на гарантии, предоставляемые моделью памяти Java. В частности, это пересмотренная модель памяти Java из Java 5, где отношения «произошло до» между чтением и записью изменчивых переменных были точно указаны. Классы ConcurrentXXX в пакете java.util.concurrent в значительной степени полагаются на это обещанное поведение непостоянных чтений, чтобы обеспечить поведение без состязаний. В модели памяти Java запись в изменчивую переменную гарантированно произойдет до чтения, если таков порядок программы; проще говоря, чтение volatile всегда будет извлекать наиболее точную версию данных в переменной. Параллельные классы используют это, чтобы гарантировать, что структуры данных могут быть обновлены одним потоком, в то время как они читаются несколькими другими потоками (в любом другом сценарии были бы условия гонки).

Или третья возможность, что jvm сама по себе не преобразует гонку в программу, свободную от гонок, но существует другой анализ, который может сделать это за нас. Так ли это?

JVM выдает инструкции ограничения памяти. Он не выполняет преобразование «гоночных» программ в «свободные от гонки». Если компилятор сгенерировал байт-код, соответствующий модели памяти Java, то JVM/JIT будет выдавать инструкции по ограничению памяти при необходимости — при чтении/записи volatile переменных, получении или освобождении мониторов на объектах и ​​т. д.

Рискуя повториться, но ни JVM, ни компилятор не преобразуют «гоночную» программу в «свободную от гонок» или наоборот. Любое обратное поведение является ошибкой либо в модели памяти Java, либо в JVM. Вам нужно будет написать программу без гонок, поняв порядок программы, порядок синхронизации и порядок «происходит до», а компилятор и JVM гарантируют, что это будет обеспечено во время выполнения.

Я рекомендую вам прочитать эту статью на InfoQ, чтобы узнать больше о том, как JVM создает ограничение памяти. инструкции и гарантирует обещания, сделанные моделью памяти Java.

person Vineet Reynolds    schedule 12.07.2011