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

Почему бы не volatile в System.Double и System.Long?

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

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

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

Это привело к тому, что мы выяснили, что такое волатильное ключевое слово. (см. эта страница). Эта страница заявляет в примечаниях:

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

Hmmm..... VolatileRead и VolatileWrite обе поддерживают наши 64-битные типы!! Таким образом, мой вопрос:

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

4b9b3361

Ответ 1

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

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

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

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

Джо Даффи знает кое-что о параллельном программировании; это то, что он должен сказать об изменчивости:

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

Ответ 2

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

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

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

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

Ответ 3

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

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

Ответ 4

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

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