Модель памяти Java и логическое значение для успеха - PullRequest
2 голосов
/ 08 ноября 2010

Я новичок в потоке Java и только недавно начал изучать модель памяти.Насколько я понимаю, модель памяти Java в ее нынешнем виде позволяет компилятору оптимизировать.

Это может усложнить многопоточный код и синхронизацию, но мой вопрос к чему-то гораздо более простому.Возьмите этот пример, так как два оператора не зависят друг от друга, возможно ли, что компилятор может изменить порядок кода в операторе try и, следовательно, прервать проверку?

boolean success = false;
try{
 MyClass.someFunction();
 success = true;
}
catch(Exception e){

}

if(success){    
    System.out.println("Sucess!");
}
else{
    System.out.println("Fail!");
}

Ответы [ 2 ]

4 голосов
/ 08 ноября 2010

Нет. Компилятор Java должен делать то, что вы ожидаете - вывести Success!, если Myclass.someFunction() вернется нормально, и Fail!, если возникнет исключение. Это происходит из семантики Java в целом и не зависит от каких-либо оптимизаций компилятора, которые может выполнять ваш компилятор (кроме тех случаев, когда это может ограничивать то, какие оптимизации допустимы).

Причина в том, что спецификация языка Java гласит, что в пределах одного потока программа должна вести себя точно так, как если бы операторы выполнялись по порядку, сверху вниз. Компилятор свободен переписывать вашу программу всеми видами неинтуитивных способов, чтобы генерировать байт-код, но он должен сохранять иллюзию, что внутри одного потока он выполняет именно те операторы, которые вы ввели в исходном коде, в правильном порядке.

Спецификация языка Java может распространить это также на многопоточные контексты и сказать, что каждый поток должен всегда видеть состояние мира, совместимое со всеми вашими потоками, выполняющими точно исходный код, который вы ввели in. Однако, (a) это очень затруднило бы написание правильной оптимизации компилятора, и многие другие полезные оптимизации были бы незаконными; и (б) это не очень поможет программистам, так как не устранит необходимость правильной синхронизации; это в основном просто превращало бы испорченные программы в менее очевидно испорченные.

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

Но важным моментом для вашего вопроса является то, что компилятор может делать все, что он хочет, за кулисами, но он не может изменить смысл вашей программы. В однопоточном контексте смысл вашей программы четко определен и не позволит компилятору делать плохие вещи, которые, как вы думаете, он может сделать.

2 голосов
/ 08 ноября 2010

Поскольку Java не может понять, что делает MyClass.someFunction(), она не может безопасно переупорядочить это утверждение. На самом деле, большинство контролеров зависимости данных полностью неспособны выйти за границы функции из-за побочных эффектов.

Потоки являются особым случаем и не являются уникальными для Java - данные попадают в регистры и не будут перезагружаться из памяти без необходимости. Решением Java является ключевое слово transient (аналогично volatile на других языках).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...