(Я знаю, что это не так, но я ищу основную причину, по которой это на самом деле работает без использования летучих, поскольку не должно быть ничего, что мешало бы компилятору сохранять переменную в регистре без изменчивых... или есть... .)
Этот вопрос проистекает из разногласий о том, что без энергозависимости компилятор (теоретически может оптимизировать любую переменную различными способами, включая сохранение ее в регистре ЦП.) Хотя в документах говорится, что это не требуется при использовании синхронизации, например блокировки переменных. Но на самом деле в некоторых случаях, по-видимому, компилятор/jit не может знать, будете ли вы использовать их или нет в своем пути к коду. Таким образом, есть подозрение, что здесь действительно происходит что-то еще, чтобы заставить модель памяти "работать".
В этом примере что мешает компилятору/jit оптимизировать _count в регистр и таким образом, приращение выполняется в регистре, а не непосредственно в памяти (позже запись в память после вызова выхода)? Если бы _count был изменчивым, казалось бы, всё было бы хорошо, но большая часть кода написана без изменчивости. Имеет смысл знать, что компилятор не должен оптимизировать _count в регистр, если он увидел в методе объект блокировки или синхронизации... но в этом случае вызов блокировки находится в другой функции.
В большей части документации говорится, что вам не нужно использовать Volatible, если вы используете вызов синхронизации, например lock.
Так что же мешает компилятору оптимизировать _count в регистр и потенциально обновить только регистр внутри блокировки? У меня такое ощущение, что большинство переменных-членов не будут оптимизированы в регистры именно по этой причине, поскольку тогда каждая переменная-член действительно должна быть изменчивой, если только компилятор не скажет, что ее не следует оптимизировать (в противном случае я подозреваю, что тонны кода потерпят неудачу). . Несколько лет назад я видел нечто подобное, глядя на C++. Локальные функциональные переменные сохранялись в регистрах, а переменные-члены класса — нет.
Итак, главный вопрос заключается в том, действительно ли это единственный способ каким образом это возможно работает без изменчивости, что компилятор/jit не будет помещать переменные-члены класса в регистры, и, следовательно, изменчивость становится ненужной?
(Пожалуйста, игнорируйте отсутствие обработки исключений и безопасность при звонках, но суть вы поняли.)
public class MyClass
{
object _o=new object();
int _count=0;
public void Increment()
{
Enter();
// ... many usages of count here...
count++;
Exit();
}
//lets pretend these functions are too big to inline and even call other methods
// that actually make the monitor call (for example a base class that implemented these)
private void Enter() { Monitor.Enter(_o); }
private void Exit() { Monitor.Exit(_o); } //lets pretend this function is too big to inline
// ...
// ...
}
Подробнее здесь: https://stackoverflow.com/questions/258 ... en-using-m
Почему не все переменные-члены должны быть изменчивыми для обеспечения безопасности потоков даже при использовании Monit ⇐ C#
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение