Ответ 1
Я видел, как вы спрашивали о GCC в некоторых комментариях, здесь вы идете.
Мне нужно иметь атомные переменные в моей программе. Раньше я использовал std::atomic<int>
, но платформа, на которой я сейчас работаю, не имеет компилятора g++, который поддерживает С++ 0x. Я использовал volatile int
и, похоже, работает, так как я еще не испытал состояние гонки в многоядерной системе, на которой я тестирую ее.
Мой вопрос: если volatile int
атомный, как std::atomic<int>
? Кроме того, создает ли барьеры памяти (что также требуется)?
Я видел, как вы спрашивали о GCC в некоторых комментариях, здесь вы идете.
Нет. volatile
не имеет никакого отношения к многопоточности. Он не защищает барьер памяти (хотя некоторые компиляторы, возможно, захотят добавить это в любом случае), и он не дает никаких гарантий относительно переупорядочения записи/записи в отношении энергонезависимых объектов.
volatile
был добавлен для поддержки записи в регистры ввода-вывода с отображением памяти, и в таких случаях, когда важно, чтобы ваша запись не оптимизировалась, но нет точных гарантий заказа. требуются нелетучие чтения/морщины.
Вы также можете прочитать this
Летучие переменные НЕ подразумевают барьеры памяти и не имеют операций exchange
или compare_exchange_*
std::atomic
. Они не позволяют компилятору поднимать нагрузку на несколько нагрузок на уровне машинного кода (и наоборот, и аналогично для магазинов), но что он.
Вам могут быть интересны следующие статьи:
Если у вас нет std::atomic
, вы можете использовать boost:: atomic или использовать низкоуровневый барьер и атомный -операционные примитивы, предлагаемые любым компилятором, который вы используете.
До С++ 0x язык не был осведомлен о потоке, поэтому он не предотвращал множественный доступ. Объявление им изменчивости поможет некоторым, но оно не будет препятствовать гонкам.
Подробнее см. http://en.wikipedia.org/wiki/Volatile_variable.
Чтобы действительно сделать операции атомарными, вам нужно использовать любой механизм блокировки вашей библиотеки потоков (win32 threads, pthreads и т.д.).
Здесь есть хорошее описание различий здесь, от Herb Sutter. Вкратце (вырезать и вставить):
Чтобы безопасно писать код без блокировки, который осуществляет связь между потоками без используя блокировки, предпочитают использовать упорядоченные атомные переменные: переменная Java/.NET, С++ 0x атомный и C-совместимый atomic_t.
Безопасное общение со специальными аппаратной или другой памяти, необычная семантика, используйте unoptimizable переменные: изменчивость ISO C/С++. Помните, что чтение и запись эти переменные не обязательно атома, однако.
volatile
в основном сообщает компилятору, что он не может делать предположения о том, что находится в определенном месте памяти. Например,
bool test = true;
while(!test)
{
/* do something (e.g. wait) */
}
компилятор может оптимизировать весь while
, поскольку он предполагает, что test
всегда истинно. Если, однако, test
в какой-то момент будет обновляться из другого места (например, для какого-то оборудования или другого потока), мы не хотим, чтобы компилятор предположил, что он знает, что находится в test
. Мы можем сказать компилятору, что с помощью volatile
.
Как утверждают другие ответы, он не дает никаких гарантий относительно того, какой порядок вещей попадает в ячейку памяти.
P.s. Я бесстыдно украл этот пример откуда-то, но не мог вспомнить, где я его видел.
Эта ссылка выглядит хорошо...
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2047.html