Почему модификаторы readonly и volatile являются взаимоисключающими? - PullRequest
9 голосов
/ 28 декабря 2008

У меня есть переменная ссылочного типа, которая равна readonly, потому что ссылка никогда не меняется, только ее свойства. Когда я попытался добавить к нему модификатор volatile, скомпилированный предупредил меня, что он не позволит использовать оба модификатора для одной и той же переменной. Но я думаю, что он должен быть нестабильным, потому что я не хочу проблем с кэшированием при чтении его свойств. Я что-то пропустил? Или компилятор не так?

Обновление Как сказал Мартин в одном из комментариев ниже: модификаторы readonly и volatile применяются только к ссылке, а не к свойствам объекта в случае объектов ссылочного типа. Вот чего мне не хватало, так что компилятор прав.

class C
{
    readonly volatile string s;  // error CS0678: 'C.s': a field cannot be both volatile and readonly
}

Ответы [ 3 ]

15 голосов
/ 28 декабря 2008

Ни модификаторы readonly, ни volatile не являются проникающими. Они применяются к самой ссылке, а не к свойствам объекта.

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

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

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


Что касается вашей озабоченности проблемами кэширования, то в IIRC существуют довольно строгие правила, когда компилятор может кэшировать результат вызова свойства. Имейте в виду, что является вызовом метода, и это довольно сложная оптимизация (с точки зрения компилятора) для кэширования его значения и пропуска его вызова. Я не думаю, что это то, что вам нужно беспокоиться слишком много.

1 голос
/ 28 декабря 2008

Поле только для чтения может быть записано только при первом создании объекта. Поэтому на процессоре не будет проблем с кэшированием, поскольку поле является неизменным и не может измениться.

0 голосов
/ 28 декабря 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...