РЕДАКТИРОВАТЬ : Я спрашиваю, что происходит, когда два потока одновременно обращаются к одним и тем же данным без надлежащей синхронизации (до этого редактирования этот момент не был четко выражен ).
У меня вопрос об оптимизации, выполняемой компилятором C # и JIT-компилятором.
Рассмотрим следующий упрощенный пример:
class Example {
private Action _action;
private void InvokeAction() {
var local = this._action;
if (local != null) {
local();
}
}
}
Пожалуйста, не обращайте внимания на то, что чтение _action
может привести к кэшированному и устаревшему значению, поскольку нет изменчивого спецификатора или какой-либо другой синхронизации. Дело не в этом :)
Разрешено ли компилятору (или на самом деле дрожание во время выполнения) оптимизировать присвоение локальной переменной и вместо этого читать _action
из памяти дважды:
class Example {
private Action _action;
private void InvokeAction() {
if (this._action != null) {
this._action(); // might be set to null by an other thread.
}
}
}
, что может генерировать исключение NullReferenceException
, когда для поля _action
установлено значение null
путем одновременного присваивания.
Конечно, в этом примере такая «оптимизация» не имела бы никакого смысла, потому что было бы быстрее сохранить значение в регистре и, следовательно, использовать локальную переменную. Но в более сложных случаях есть ли гарантия, что это сработает должным образом без повторного чтения значения из памяти?