.Net: Энергозависимая 32-битная и энергонезависимая 64-битная и поточная безопасность. Какой лучший способ справиться с 64 бит? - PullRequest
2 голосов
/ 19 января 2012

Я понимаю, что volatile предотвращает выполнение определенных (но не всех) оптимизаций переменных. Хотя документация немного запутывает эту тему (например, Википедия и MSDN противоречат), я понимаю, что volatile применяет половину памяти, которая предотвращает некоторые операции переупорядочения. (ссылка Албахари).

Я также понимаю, что это предотвращает использование регистров, что означает, что чтение никогда не может устареть из-за, например, подъема переменных в циклах.

Я также знаю из опыта, что компилятор формирует разные (недокументированные AFAIK) оптимизации для разных типов данных, делая область несколько непредсказуемой.

Однако что-то для меня остается совершенно неясным. 64-битные значения, такие как long, не могут быть украшены volatile.

Так что мой вопрос в том, как обрабатывать такие переменные, чтобы они рассматривались как эквивалент изменчивых 32-битных типов значений?

Это выглядит как несоответствие, так как я не считаю, что 32- и 64-битные значения должны рассматриваться по-разному.

EDIT

Кроме того, почему барьер памяти гарантирует, что компилятор напишет ASM, который будет извлекать значение из ОЗУ, а не из регистра? Я понимаю, почему volatile сделает это.

Ответы [ 3 ]

2 голосов
/ 19 января 2012

Это просто ограничение, накладываемое 32-битным джиттером, как у обычного x86.Он не может гарантировать, что переменные будут выровнены лучше, чем по адресу, кратному 4. В основном потому, что распределитель кучи не обещает лучшей работы.И не было предпринято никаких усилий, чтобы адреса стеков были выровнены лучше, чем 4. Соответственно, 64-битная переменная может охватывать границу строки кэша.И поэтому не может быть атомным.

1 голос
/ 19 января 2012

Посмотрите на этот замечательный блог от Эрика Липперта и следите за заключением статьи ;-)
Особенно в 32 системах доступ к 64-битным длинным не атомарен!

0 голосов
/ 19 января 2012

Первоначально это был комментарий, но он стал ответом.

Не могли бы вы использовать Thread.MemoryBarrier для достижения аналогичной цели?Хотя это и раздражает, я думаю, что разумно, что у вас не может быть изменчивого long, потому что компилятор не может гарантировать поддержку на всех платформах;в то время как с 32-битными значениями это возможно.

Thread.MemoryBarrier - это способ во время выполнения указать ОС сделать это от вашего имени;вместо этого выгрузить проблему в ОС;точно так же, как методы Interlocked не являются сокращением для инструкций машинного кода, выполняющих одну и ту же вещь - потому что они не могут быть гарантированно доступны на каждом процессоре., применяется на многих уровнях: по крайней мере, с компилятором, временем выполнения и процессором.В этом случае .Net может гарантировать все три для 32-битных значений, так как 32-битный является повсеместным.Однако поддержка ЦП не всегда доступна для 64-разрядных систем через .Net;а отметка только 2 из 3-х полей недостаточна, чтобы гарантировать, что код все еще будет работать.

Изменить (в ответ на ваш дополнительный комментарий в конце вашего вопроса)

Насколько я понимаю, MemoryBarrier заключается в том, что это сигнал под управлением ОС для всех потоков, чтобы сбросить все записи в ОЗУ;и затем принудительно перезагружая текущий поток из ОЗУ (обратно в регистры), таким образом гарантируя, что текущий поток имеет последнюю версию значения.

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