Подтвердить что ты не робот

Неустойчивые переменные

Недавно у меня было интервью с компанией-разработчиком программного обеспечения, которая задала мне следующий вопрос:

Можете ли вы описать мне, что добавляет изменчивость перед переменными? Можете ли вы объяснить мне, почему это важно?

Большинство моих знаний о программировании взяты из C, но позиция работы для С# (я думал, что могу добавить этот бит информации, если это необходимо для конкретного вопроса)

Я ответил, сказав, что просто позволяет компилятору знать, что переменная может использоваться в процессах или потоках и что она не должна использовать оптимизацию для этой переменной; так как оптимизация может ухудшить поведение. В двух словах это предупреждение для компилятора.

По словам интервьюера, однако, это наоборот, а ключевое слово volatile предупреждает ОС, а не компилятор.

Я был немного озадачен этим, поэтому я провел некоторое исследование и фактически нашел противоречивые ответы! Некоторые источники говорят об этом для компилятора, а другие - для ОС.

Что это? Различается ли он по языку?

4b9b3361

Ответ 1

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

Это действительно зависит от того, что он подразумевал под "ОС". Говорят ли они о "авансовой ОС", чистой программной стороне вещей или о том, что они могут неправильно истолковывать "ОС" в качестве аппаратно-программных отношений, то есть RTE и MMM (я видел либо предположения и сравнения в некоторых из моих личных интервью). Я думаю, следует отметить, что эти два совершенно разные! Если он говорит о первом, тогда НЕТ volatile не "информирует" ОС. Если они говорят о последнем, то да (это слабое да). На данный момент вы находитесь в сфере различий между языками. Как отметил Коди Грей, С# - это управляемый язык, и поэтому последнее определение ОС действительно "получает уведомление" о переменной и о мерах предосторожности.

Но также в любом случае или в определении ОС компилятор делает специально управляет и обрабатывает поле volatile, независимо от языка. В противном случае, почему ключевое слово в первую очередь?

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

Ответ 2

Я ответил, сказав, что это просто позволяет компилятору знать, что переменная может использоваться в процессах или потоках и что она не должна использовать оптимизацию для этой переменной; так как оптимизация может ухудшить поведение. В двух словах это предупреждение для компилятора.

Это происходит в правильном направлении для С#, но пропускает некоторые важные аспекты.

Прежде всего, удалите "процессы" целиком. Переменные не разделяются между процессами на С#.

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

В-третьих, не думайте об этом как о предупреждении компилятору. Это директива для компилятора: генерировать код, который гарантированно соответствует спецификации для переменных переменных. Как это делает компилятор.

Фактический ответ на вопрос

Можете ли вы описать мне, что добавляет изменчивость перед переменными?

: Компилятор С# и среда выполнения имеют отличную широту для переопределения переменных чтения и записи по любой причине, по их мнению, подходят. Они ограничены только теми переупорядочениями, которые сохраняют смысл программ в одном потоке. Итак, "x = y; a = b;" может переместить чтение b до чтения до y; это законно, потому что результат не изменился. (Это не единственное ограничение при повторном заказе, но в некотором смысле это самое фундаментальное). Однако повторное упорядочение разрешено быть заметным на нескольких потоках; возможно, что в другом потоке наблюдается, что b считывается до y. Это может вызвать проблемы.

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

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

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

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

Теперь рассмотрим ваш ответ в контексте C.

Вопрос некорректен относительно C. В С# volatile является модификатором в объявлениях переменных-членов; в C, это часть типа. Поэтому выражение "перед переменной" неоднозначно; где перед переменной? Там разница между volatile int * x и int * volatile x. (Вы видите разницу?)

Но что более важно: спецификация C не гарантирует, что volatile будет иметь какое-либо конкретное поведение в отношении потоков. Если ваш компилятор C делает это расширение языка вашим поставщиком компилятора. Волатильность в C гарантируется определенным поведением в отношении отображаемых в памяти IO, длинных переходов и сигналов, и что все; если вы полагаетесь на него, чтобы иметь определенное поведение в отношении потоков, тогда вы пишете не переносимый код.

По словам интервьюера: это наоборот, а ключевое слово volatile предупреждает ОС, а не компилятор.

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