Ключевое слово volatile очень субъективно для языка и платформы, на которой оно реализовано. В то время как Java обеспечивает согласованное поведение volatile для всех архитектур, это не относится к языкам, которые напрямую скомпилированы в платформу собственного компьютера, например, в случае C / C ++. Попробуем разобраться, почему это так.
Пусть a, b являются членами набора программных действий P, а v_ {n} (a) будет функцией, которая применяет требование изменчивости к действию, где нижний индекс _n обозначает _n-ю итерацию, в которой применяется изменчивое действие. , а \ rightarrow - оператор предшествования, который объяснялся ранее. Для всех действий программы действуют следующие правила:
v_n (а) \ rightarrow v_ {n + 1} (а)
a \ rightarrow v_n (b) \ Rightarrow a \ rightarrow v_ {n + i} (b) где i \ in \ mathbb {N}
Правило 1 говорит, что все изменчивые функции обеспечивают общий порядок, где функция v_ {n} (a) всегда предшествует v_ {n + 1} (a), где правило 2 говорит, что если действие a предшествует изменчивой функции для действия b на _n-й итерации, то действие a обязательно должно предшествовать всем последующим изменчивым функциям, применяемым к b.
Это очень сильное требование к памяти в Java, на самом деле оно намного сильнее, чем по сравнению с C / C ++. Спецификация языка C / C ++ не имеет такого ограничения на порядок памяти и оставляет на усмотрение реализации компилятора решение о том, как энергонезависимые действия упорядочиваются вокруг изменчивых действий.
Рассмотрим, как эти правила влияют на выполнение программы, на простом примере кода:
int a = 0;
int b = 0;
volatile int count = 0;
a = 1;
count = 1;
b = 2;
count = 2;
В C / C ++ ключевое слово volatile гарантирует только то, что переменные count не могут быть переупорядочены относительно друг друга, т.е. если count == 2, то ему обязательно должно предшествовать count = 1. Однако нет ни гарантии, что a == 1, ни b == 2.
В Java, учитывая более строгую гарантию, определенную выше, тогда, если count == 1, тогда утверждение a == 1 должно быть истинным. Точно так же, если count == 2, тогда утверждение, что a == 1 && b == 2 должно быть истинным. Именно это означает строгая гарантия памяти, которую Java предлагает, а C / C ++ - нет.
Однако это не означает, что C / C ++ не будет вести себя так же, как Java. Будет ли это так, зависит от (1) того, выполняет ли компилятор какое-либо переупорядочение кода, которое может быть в неожиданном, но допустимом порядке, и (2) поддерживает ли архитектура базовой машины такой же строгий порядок памяти при условии, что компилятор не производит неожиданного переупорядочивания кода.
Например, компиляция кода на gcc с -O0, установленным на всех платформах x86, будет соответствовать модели памяти Java (и строже, чем), но другие архитектуры, такие как PowerPC, Alpha, Itanium, все поддерживают более слабую модель памяти, которая может показывать удивительную программу. поведение, которого программист может не ожидать. Будьте осторожны, лектор!
В любом случае, если вас интересуют дополнительные правила согласованности модели памяти, вы можете посмотреть объяснение Intel модели памяти x86, в котором подробно объясняются нюансы упорядочения памяти. Наслаждаться!
person
sachin10
schedule
12.11.2013