Какая разница в использовании volatile между C / C ++ и C # / Java?

Я нашел это во многих ссылках, которые упоминают, что volatile в C / C ++ является слабым и может вызвать проблемы в параллельной среде на нескольких процессорах, но это (volatile) может использоваться как механизм связи между разными процессорами в C # / Java. Кажется, что это ключевое слово более строгое в C # / Java, чем в C / C ++, но в чем разница / влияние между ними?

Вот ссылка на volatile в C / C ++.
Почему volatile не считается полезным в многопоточном программировании на C или C ++?

13

Решение

За C # / Java, «volatile«сообщает компилятору, что значение переменной никогда не должно кэшироваться, поскольку ее значение может изменяться вне области самой программы. Компилятор тогда избегает любых оптимизаций, которые могут привести к проблемам, если переменная изменяется» вне ее контроля » ,

В C / C ++, «volatile«Требуется при разработке встроенных систем или драйверов устройств, где необходимо прочитать или записать аппаратное устройство с отображением в памяти. Содержимое конкретного регистра устройства может измениться в любое время, поэтому вам необходимо»volatilemsgstr «ключевое слово, чтобы компилятор не оптимизировал такой доступ.

11

Другие решения

Ключевое слово volatile очень субъективно по отношению к языку и платформе, на которой оно реализовано. Хотя Java обеспечивает согласованное поведение volatile во всех архитектурах, это не относится к языкам, которые непосредственно компилируются в платформу машинного оборудования, например, в случае C / C ++. Давайте попробуем понять, почему это так.

Пусть a, b будет членом набора программных действий P, а v_ {n} (a) будет функцией, которая применяет требование к изменчивости к действию, где нижний индекс _n обозначает _n-ю итерацию, в которой применяется изменяемое действие и \ rightarrow будет оператором предыдущего, что объяснялось ранее. Для всех действий программы выполняются следующие правила:

v_n (a) \ rightarrow v_ {n + 1} (a)

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 на _-й итерации, то действие 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 должно быть истинным. Точно так же, если считать == 2, то утверждение, что == 1 && b == 2 должно быть правдой. Это то, что подразумевается под строгой гарантией памяти, которую Java предлагает, а C / C ++ — нет.

Однако это не означает, что C / C ++ не будет вести себя так же, как Java. Если это произойдет, зависит от (1) того, выполняет ли компилятор какое-либо переупорядочение кода, которое может быть в неожиданном порядке, но законном порядке, и (2) поддерживает ли базовая архитектура компьютера тот же строгий порядок памяти, при условии, что Компилятор не выполняет никаких удивительных переупорядочений кода.

Например, компиляция кода в gcc с параметром -O0, установленным на всех платформах x86, будет соответствовать (и более строгой, чем) модели памяти Java, но другие архитектуры, такие как PowerPC, Alpha, Itanium, поддерживают слабую модель памяти, которая может демонстрировать удивительные программы. поведения, которые программист может не ожидать. Будьте Лектором!

В любом случае, если вас интересуют дополнительные правила согласованности моделей памяти, вы можете посмотреть объяснение Intel модели памяти x86, где нюансы упорядочения памяти объяснены достаточно подробно. Наслаждайтесь!

7

В C / C ++ volatile не имеет особой семантики, относящейся к многопоточности, поэтому поведение в этом контексте зависит от платформы. C # и Java предоставляют определенную семантику многопоточности для volatile, Таким образом, вы знаете, что вы получаете, и можете положиться на это.

3
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector