2015-09-22 9 views
2

В настоящее время я изучаю модель памяти Java и как она влияет на переупорядочивания, которые может сделать компилятор. Тем не менее, я немного смущен внешними операциями. JMM определяет их как действие, которое можно наблюдать за пределами операции. Отключение this question, я понимаю внешние действия, такие как печать значения, запись в файл, сетевые операции и т. Д.Переупорядочение внешних операций в модели памяти Java

Теперь, как внешние действия влияют на переупорядочение? Я думаю, что очевидно, что внешнее действие не может быть переупорядочено с помощью другого внешнего действия, так как это изменит наблюдаемое поведение программы (и, следовательно, не является допустимым преобразованием в соответствии с JMM). Но как насчет переупорядочения внешнего действия с нормальным доступом к памяти или действия синхронизации? Например:

volatile int v = 5; 
int x = v; 
System.out.println("!"); 

Можно распечатать и int x = v быть заказана здесь? Я не вижу, как это меняет поведение, но чтение volatile v совпадает с просмотром монитора, поэтому я не думаю, что переупорядочение действительно.

+0

Мое понимание (которое может быть ошибочным) заключается в том, что нет приоритета в отношении защищенных операций. Поэтому ни изменчивое чтение, ни внешняя запись не могут быть переупорядочены, поэтому ваш пример с тремя строками остается фиксированным. Вы можете протестировать его, вставив его в метод и называя его несколько (сотни?) Тысяч раз, используя оба -server и -XX: + PrintCompilation и сравнивая результаты JIT. – lscoughlin

ответ

1

Внешние действия добавлены, чтобы избежать неожиданных результатов:

class ExternalAction { 

    int foo = 0; 

    void method() { 
    jni(); 
    foo = 42; 
    } 

    native void jni(); /* { 
    assert foo == 0; 
    } */ 
} 

Предполагая, что метод JNI был реализован запустить то же утверждение, вы не ожидали бы, что это провал. Компилятор JIT не может определить результат чего-либо внешний, так что JMM запрещает такие переупорядочивания.