Почему не энергозависимые на System.Double и System.Long? - PullRequest
40 голосов
/ 18 января 2011

Вопрос, подобный моему, был задан , но мой немного другой.Вопрос в том, почему ключевое слово volatile не разрешено в C# для типов System.Double и System.Int64 и т. Д .?"

На первый взгляд я ответил своему коллеге: «Ну, на32-битный компьютер, эти типы требуют по крайней мере двух тактов, чтобы войти в процессор, и .Net Framework намерен абстрагировать детали, относящиеся к процессору, как этот. "На что он отвечает: «Это ничего не абстрагирует, если мешает использовать функцию из-за проблемы, связанной с процессором!»

Он подразумевает, что детали, относящиеся к процессору, не должны отображаться человеку, использующемуфреймворк, который "абстрагирует" такие детали от программиста.Таким образом, фреймворк (или C #) должен абстрагировать их и делать то, что нужно, чтобы предложить те же гарантии для System.Double и т. Д. (Будь то семафор, барьер памяти или что-то еще).Я утверждал, что фреймворк не должен добавлять накладные расходы семафора на volatile, потому что программист не ожидает таких накладных расходов с таким ключевым словом, потому что семафор не нужен для 32-битных типов.Большие издержки для 64-битных типов могут быть неожиданностью, поэтому лучше .NET Framework просто не разрешать это, и заставлять вас создавать свой семафор для больших типов, если накладные расходы приемлемы.

Это привело к нашему исследованию того, что такое ключевое слово volatile.(см. эту страницу).Эта страница в примечаниях гласит:

В C # использование модификатора volatile для поля гарантирует, что весь доступ к этому полю использует VolatileRead или VolatileWrite.

Хммм..... VolatileRead и VolatileWrite оба поддерживают наши 64-битные типы !!Поэтому мой вопрос:

"Почему ключевое слово volatile не разрешено в C# для типов System.Double и System.Int64 и т. Д .?"

Ответы [ 4 ]

17 голосов
/ 18 января 2011

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

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

Смысл этой функции в том, чтобы сказать: «Я отказался от удобных абстракций, гарантируемых однопоточным программированием, и охватил возможный выигрыш в производительности благодаря глубокому знанию моего процессора, зависящего от реализации.«.Вы должны ожидать, что меньше абстракций в вашем распоряжении, когда вы начнете использовать техники с низкой блокировкой, а не больше абстракций .

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

12 голосов
/ 18 января 2011

Да. Причина в том, что вы даже не можете прочитать double или long за одну операцию. Я согласен, что это плохая абстракция. У меня такое ощущение, что причина в том, что их атомарное чтение требует усилий, и это будет слишком умно для компилятора. Таким образом, они позволяют вам выбрать лучшее решение: lock ing, Interlocked и т. Д.

Интересно то, что они могут фактически считываться атомарно на 32-битных, используя регистры MMX. Это то, что делает JIT JIT компилятор. И они могут быть прочитаны атомарно на 64-битной машине. Поэтому я считаю, что это серьезный недостаток в дизайне.

5 голосов
/ 18 января 2011

Не совсем ответ на ваш вопрос, но ...

Я почти уверен, что документация MSDN, на которую вы ссылались, неверна, когда в ней говорится, что "использование модификатора volatile в поле гарантирует, что весь доступ к этому полю использует VolatileRead или VolatileWrite" .

Непосредственное чтение или запись в поле volatile создает только половину ограждения (ограждение приобретения при чтении и ограждение освобождения при записи).

Методы VolatileRead и VolatileWrite используют MemoryBarrier внутри, что создает полный забор.

Джо Даффи знает кое-что о параллельном программировании; вот что он говорит о летучем :

(Кроме того, многие люди задаются вопросом о разница между нагрузками и хранилища переменных, помеченных как изменчивые и вызывает Thread.VolatileRead и Thread.VolatileWrite. Различия является то, что прежние API реализован сильнее, чем в сочетании код: они достигают приобретения / выпуска семантика, испуская полные заборы на правая сторона. API больше дорого звонить тоже, но хотя бы позволит вам определиться с база данных по сайту отдельные грузы и магазины нуждаются в ММ гарантирует.)

3 голосов
/ 07 июля 2011

Это простое объяснение наследия. Если вы прочтете эту статью - http://msdn.microsoft.com/en-au/magazine/cc163715.aspx,, вы обнаружите, что единственная реализация среды выполнения .NET Framework 1.x была на компьютерах с архитектурой x86, поэтому Microsoft имеет смысл реализовать ее для модели памяти с архитектурой x86. x64 и IA64 были добавлены позже. Таким образом, базовая модель памяти всегда была моделью x86.

Могло ли это быть реализовано для x86? Я на самом деле не уверен, что это может быть полностью реализовано - ссылка на двойное значение, возвращаемое из собственного кода, может быть выровнена по 4 байта вместо 8. В этом случае все ваши гарантии атомарного чтения / записи больше не выполняются. *

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