Правда ли, что «volatile» в пользовательской программе обычно указывает на ошибку? - PullRequest
1 голос
/ 07 мая 2019

Когда я гуглял о «изменчивом» и использовании его пространства пользователя, я обнаружил письма между Теодором Цо и Линусом Торвальдсом.По словам этих великих мастеров, использование «volatile» в пользовательском пространстве может быть ошибкой. Проверьте обсуждение здесь

Хотя у них есть некоторые объяснения, но я действительно не мог понять.Может ли кто-нибудь использовать простой язык, чтобы объяснить, почему они так сказали?Мы не должны использовать volatile в пользовательском пространстве ??

1 Ответ

9 голосов
/ 07 мая 2019

volatile говорит компилятору, что каждое чтение и запись имеет наблюдаемый побочный эффект;таким образом, компилятор не может делать какие-либо предположения о том, что два чтения или две записи в строке имеют одинаковый эффект.

Например, обычно следующий код:

int a = *x;
int b = *x;
if (a == b)
    printf("Hi!\n");

Может бытьоптимизировано для:

printf("Hi!\n");

Что делает volatile, так это сообщает компилятору, что эти значения могут приходить откуда-то вне контроля программы, поэтому он должен фактически прочитать эти значения и выполнить сравнение.

Многие люди ошиблись, думая, что они могут использовать volatile для создания структур данных без блокировки, которые позволят нескольким потокам совместно использовать значения, и они могли наблюдать влияние этих значений в других потоках..

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

Вместо этого вам нужно либо использовать блокировки или какой-либо другой стандартный механизм параллелизма для связи между потоками, либо использовать барьеры памяти , либо использовать C11 / C ++11 атомарные типы и атомарные операции .Блокировки гарантируют, что весь регион кода имеет эксклюзивный доступ к переменной, которая может работать, если у вас есть значение, которое слишком велико, слишком мало или не выровнено для атомарной записи в одной операции, в то время как барьеры памяти и атомарные типыа операции обеспечивают гарантии того, как они работают с ЦП, чтобы гарантировать, что кэши синхронизируются или операции чтения и записи выполняются в определенных порядках.

В основном, volatile в основном полезен, когда вы взаимодействуете с однимаппаратный регистр, который может изменяться вне контроля программ, но может не требовать каких-либо специальных атомарных операций для доступа.Или его можно использовать в обработчиках сигналов , где, поскольку поток может быть прерван, а обработчик запущен, а затем управление возвращено в том же потоке, вам необходимо использовать значение volatile, если вы хотитепередать флаг прерванному коду.

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

...