Разрешенная оптимизация компилятора C # для локальных переменных и извлечение значения из памяти

РЕДАКТИРОВАТЬ : Я спрашиваю, что происходит, когда два потока одновременно обращаются к одним и тем же данным без надлежащей синхронизации (до этого редактирования этот момент не был четко выражен ).

У меня вопрос об оптимизации, выполняемой компилятором 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 путем одновременного присваивания.

Конечно, в этом примере такая «оптимизация» не имела бы никакого смысла, потому что было бы быстрее сохранить значение в регистре и, следовательно, использовать локальную переменную. Но в более сложных случаях есть ли гарантия, что это сработает должным образом без повторного чтения значения из памяти?

11
задан thaller 7 October 2011 в 11:47
поделиться