Re[6]: Многопоточность
От: MadHuman Россия  
Дата: 22.12.20 09:11
Оценка: +1
Ф>>>>>volatile запрещает оптимизации компилятора в отношении поля. В ином случае Disposed может вернуть false там, где должен быть true, потому что false может "застрять" в регистре, куда ранее была зачитана ячейка памяти.
MH>>>>
MH>>>>internal bool Disposed => _disposed != 0;
MH>>>>


MH>>>>когда будет вызван гетер для Disposed — вариантов кроме как прочитать _disposed из памяти нет. не будет он из регистра читаться


Ф>>>Такие гарантии может дать только volatile, т.е. запрет оптимизаций.

MH>>нет. нет других вариантов для реализации этого метода кроме как генерировать ассемблерную инструкцию чтения памяти.

Ф>а завтра может быть пара из mov и cmp. Например потому, что это другой процессор, и там джиттер работает немного иначе.

mov — всё равно из памяти будет читать
то есть другого варианта нет
дело не в том как джиттер работает. дело в том что при передаче управления в метод-геттера в теле метода надо читать филд, из памяти.


MH>>volatile — актуальна, когда в рамках одного метода надо запретить компилятору оптимизации. вот в таком кейсе (в жирном методе с рядом обращений к филду) он вполне может после 1-го чтения, запомнить результат в регистре

MH>>и затем к нему обращаться.

Ф>Проблема как раз в том, что метод вполне себе может быть жирным, и ты это никак не можешь проконтролировать. Просто очередной программист напишет пяток Receive() и пару Send() — всё, приехали: вот он простор для компиляторных оптимизаций.

дак а я о чём? конечно может быть какой-то метод жирным и в нём ряд обращений к полю компилятор (а затем джит) заоптимит так что 1-й раз прочитается в регистр а затем из него.
но мы рассматриваем ситуацию топик-стартера, то есть речь об методе
internal bool Disposed => _disposed != 0;

этот метод не жирный. здесь единственный случай чтения поля, и его можно только прочитать из памяти. не тот случай когда нужен volatile.

более того — если посмотреть в целом на ситуацию, то volatile не нужен. т.к. даже если мы гарантированно прочитали память, то в следующий момент ( может даже ещё до выхода из геттера) _disposed может оказаться выставленным,
и вызывающая сторона ошибочно посчитает что ещё не диспозед, хотя уже диспозед. то есть volatile никак не предотвратит на 100% вызывающую Disposed сторону от ошибочного действия.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.