Это звучит как отличный ответ.

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

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

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

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

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

Хммм .....VolatileRead а такжеVolatileWrite оба поддерживают наши 64-битные типы !! Мой вопрос, то есть

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

 Zach Saw07 июл. 2011 г., 13:25
Обратите внимание, что Microsoft исправила страницу ибольше никогда говоритIn C#, using the volatile modifier on a field guarantees that all access to that field uses VolatileRead or VolatileWrite.

Ответы на вопрос(4)

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

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

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

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

 Andrey18 янв. 2011 г., 19:29
не могли бы вы объяснить, почемуvolatile не допускается дляlong а такжеdouble? теоретически можно сделать несколько трюков, чтобы сделать их волатильными.
 Limited Atonement18 янв. 2011 г., 21:19
Спасибо за ваш комментарий. Вы упомянули: «... обладаю глубокими знаниями в области реализации моего процессора». сразу после того, как сказал "писать ... портативные ... программы ...". Итак, нас интересует «мой» процессор или переносимость (примерно все процессоры или защитное программирование)? Я, конечно, согласен с тем, что чем больше «металла» (многопоточность является темой), тем больше «реализация». Я думаю, однако, что ключевое слово, такое как volatile, может предложить решение, не зависящее от реализации, что-то вроде «это ключевое слово оборачиваетсяVolatileRead а такжеVolatileWrite". Как вы думаете?
 Andrey18 янв. 2011 г., 21:25
@ Ограниченное искупление, хорошо, я согласен с Эриком.volatile это довольно низкоуровневый материал. использованиеInterlocked а такжеlocks. Материал низкого уровня не может быть переносимым. околоVolatileRead прочитайте ответ LukeH. Они довольно дорогие и имеют другой эффектvolatile ключевое слово (они сбрасывают все кэши).
 Eric Lippert18 янв. 2011 г., 19:49
@ Андрей: Конечно, CLR позволяет нам сделать изменчивый, неатомарный доступ к полям типа double (я думаю ... не пробовал это). Дизайнеры C # решили не допустить этого; все изменчивые обращения также атомарны в C #. Если вы относитесь к тому типу людей, которым нужен изменчивый, но неатомарный доступ к переменным, содержащим большие структуры, то C # может оказаться не лучшим языком для вас. Если вы хотите использовать C # для этого, вы всегда можете использовать VolatileRead и VolatileWrite; обратите внимание, что при этомна практике вызывает полный барьер памяти, хотя это негарантия API, и это может измениться в будущем.
 Andrey18 янв. 2011 г., 21:22
Я согласен с тем, что сбивать с толку неатомарное чтение / запись непонятно. но в явеlong является летучим и атомным. в 32-битных системах это достигается с помощью регистров XMM, которые допускают атомарную загрузку из памяти и имеют 128. Я думаю, что CLR должен реализовать нечто подобное.

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

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

 Limited Atonement18 мая 2015 г., 21:02
Это звучит как отличный ответ.
Решение Вопроса

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

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

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

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

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

 Zach Saw07 июл. 2011 г., 13:55
Да, он генерирует их только тогда, когда это необходимо - в противном случае вы подразумеваете, что независимо от необходимости всегда требуется половинный забор при нестабильных операциях чтения / записи (что также может быть сделано на x86 / x64, но это не так).
 Andrey18 янв. 2011 г., 19:05
я услышал другое мнение:igoro.com/archive/volatile-keyword-in-c-memory-model-explained прокрутите вниз до таблицы в разделе «Модель памяти и операции .NET»
 LukeH18 янв. 2011 г., 19:12
@ Андрей: обаVolatileRead а такжеVolatileWrite вызовMemoryBarrier внутренне. Так что я не понимаю, как они могут иметь более слабую семантику, чемMemoryBarrier в одиночку, о чем говорит эта таблица.
 Andrey18 янв. 2011 г., 19:07
странно, «на самом деле они создают полные заборы»,albahari.com/threading/part4.aspx
 LukeH07 июл. 2011 г., 13:54
@Zach: Но разве это не потому, что сама модель памяти x86 гарантирует, что чтения имеют семантику чтения, а записи имеют семантику выпуска независимо? Возможно, мне следовало бы перефразировать его так: «Непосредственное чтение или запись в изменчивое поле создает только половину ограждения (ограждение приобретения при чтении и ограждение выпуска при записи)и только если это необходимо для принудительного применения модели памяти CLR на текущем оборудовании"Это имеет какой-то смысл, или я упускаю суть?

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

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

 Henk Holterman18 янв. 2011 г., 18:42
Дело в том, если они могут быть атомарно читать / писать наЛюбые реализация CLI.
 Limited Atonement18 янв. 2011 г., 18:45
«У меня есть ощущение, что причина в том, что их атомарное чтение требует усилий, и это будет слишком умно для компилятора». Но это не умнее, чем для других типов. В любом случае, просто используйтеSystem.Threading.Thread.VolatileRead заSystem.Double а такжеSystem.Int32, Не нужно больше «умов» или чего-то еще, чтобы просто делать то, что вы делаете с другими вариабелями.
 Andrey18 янв. 2011 г., 18:59
@ Ограниченное призвание ИскупленияVolatileRead на простом утверждении это то, что я назвалслишком умный, Вы можете поспорить об этом, но это решение команды компиляторов. Я бы хотел, чтобы Эрик Липпер пролил немного света.
 Andrey18 янв. 2011 г., 19:00
@ Хенк Холтерман, на самом деле это довольно слабое место. Java позволяетvolatile наlong а такжеdouble и он имеет гораздо больше реализаций, чем CLI.
 Limited Atonement18 янв. 2011 г., 18:47
@Henk Все реализации CLI имеютSystem.Threading.Thread.VolatileRead правильно? Или, может быть, я не понимаю ваш смысл.

Ваш ответ на вопрос