Использование C / Pthreads: общие переменные должны быть изменчивыми? - PullRequest
28 голосов
/ 17 сентября 2008

В языке программирования C и Pthreads в качестве библиотеки потоков; переменные / структуры, которые разделены между потоками, должны быть объявлены как volatile? Предполагая, что они могут быть защищены замком или нет (возможно, барьеры).

Говорит ли об этом стандарт Pthread POSIX, это зависит от компилятора или нет?

Изменить, чтобы добавить: Спасибо за отличные ответы. Но что, если вы не используете блокировки; что если вы используете барьеры например? Или код, который использует примитивы, такие как compare-and-swap для прямого и атомарного изменения общей переменной ...

Ответы [ 13 ]

0 голосов
/ 16 сентября 2010

Я не понимаю. Как синхронизация примитивов заставляет компилятор перезагружать значение переменной? Почему бы просто не использовать последнюю имеющуюся копию?

Volatile означает, что переменная обновляется вне области кода, и, таким образом, компилятор не может предполагать, что он знает ее текущее значение. Даже барьеры памяти бесполезны, так как компилятор, который не замечает барьеры памяти (верно?), Все равно может использовать кэшированное значение.

0 голосов
/ 17 сентября 2008

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

Для простых значений (int и float их различных размеров) мьютекс может быть излишним, если вам не нужна явная точка синхронизации. Если вы не используете мьютекс или какую-либо блокировку, вы должны объявить переменную volatile. Если вы используете мьютекс, все готово.

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

0 голосов
/ 17 сентября 2008

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

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

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

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

...