2017-02-01 3 views
2

Как я понимаю, volatile -qualified value означает, что мы должны перейти к адресу и принять самое новое значение независимо от того, когда мы к нему обращаемся.
Почему волатильность делает неопределенное поведение

Сейчас я читаю книгу Эффективное Современный C++ и я не понимаю, почему volatile делает UB здесь:

volatile int vi(0); // initialize vi to 0 
vi = 10; // set vi to 10 
std::cout << vi; // read vi's value 
++vi; // increment vi to 11 
vi--; // decrement vi to 10 

Во время выполнения этого кода, если другие потоки читают значение vi, они могут видеть что угодно (например, -12, 68, 4090727-ничего!). Такой код имел бы неопределенное поведение, потому что эти операторы изменяют vi, поэтому, если другие потоки одновременно читают vi, есть одновременно читатели и писатели с памятью, которые не являются std :: atomic и не защищены мьютексом, и это определение гонка данных.



На мой взгляд, если другие потоки могут видеть 0, 10 или 11, я могу понять, но почему эта книга говорит, что «они могут увидеть что-нибудь»?

+0

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

+4

несинхронизированный доступ => неопределенное поведение => все может случиться. volatile - не примитив синхронизации. – Mat

+3

'volatile' не имеет отношения к потоку. Используйте синхронизацию 'atomic' или' mutex'. – Jarod42

ответ

0

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

Независимо от того, будут ли такие машины, которые могут запускать C++, иметь такие проблемы с метастабильностью [разработчики аппаратного обеспечения много узнали о том, как их избежать за последние 35 лет], авторы Стандарта не хотели налагать требования, которые правдоподобные реализации не могли бы встретиться.

6

В этом разделе говорится о распространенном заблуждении, что volatile безопасен для многопоточного программирования. Если разные потоки читаются и записываются в vi одновременно, тогда у вас есть гонка данных , потому что нет никаких гарантий синхронизации или атомарности. Гонки данных - это неопределенное поведение на C++, так что «что-то» действительно что-то значит.

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

Для получения более подробной информации о том, почему volatile небезопасен для такого рода вещей, см. Ссылки на this site.

Смежные вопросы