ссылочное присвоение является атомарным итак, почему Взаимно блокируется. Exchange (касательно Объекта, Объекта) необходимый?

В моем многопоточном asmx веб-сервисе у меня было поле класса _allData моего собственного типа SystemData, который состоит из немногих List<T> и Dictionary<T> отмеченный как volatile. Системные данные (_allData) обновляется время от времени, и я делаю это путем создания другого названного объекта newData и заливка это - структуры данных с новыми данными. Когда это сделано, я просто присваиваюсь

private static volatile SystemData _allData

public static bool LoadAllSystemData()
{
    SystemData newData = new SystemData();
    /* fill newData with up-to-date data*/
     ...
    _allData = newData.
} 

Это должно работать, так как присвоение является атомарным и потоки, которые имеют ссылку на старые данные, продолжают использовать его, и у остальных есть новые системные данные сразу после присвоения. Однако мой коллега сказал это вместо использования volatile ключевое слово и простое присвоение я должен использовать InterLocked.Exchange потому что он сказал, что на некоторых платформах не гарантируется, что ссылочное присвоение атомарное. Кроме того: когда я объявляю the _allData поле как volatile

Interlocked.Exchange<SystemData>(ref _allData, newData); 

производит предупреждение "ссылки на энергозависимое поле, не будет рассматриваться как энергозависимый", Что я должен думать об этом?

104
задан casperOne 23 September 2011 в 03:52
поделиться

3 ответа

Здесь возникает множество вопросов. Рассматривая их по одному:

присвоение ссылки является атомарным, так зачем нужен Interlocked.Exchange (ref Object, Object)?

Назначение ссылки является атомарным. Interlocked.Exchange выполняет не только присвоение ссылок. Он считывает текущее значение переменной, убирает старое значение и присваивает переменной новое значение, все как атомарная операция.

мой коллега сказал, что на некоторых платформах не гарантируется, что присвоение ссылок является атомарным. Прав ли был мой коллега?

Нет. Назначение ссылок гарантированно атомарно на всех платформах .NET.

Мой коллега исходит из ложных предпосылок. Означает ли это, что их выводы неверны?

Не обязательно. Ваш коллега может давать вам хороший совет по плохим причинам. Возможно, есть другая причина, по которой вам следует использовать Interlocked.Exchange. Программирование без блокировок безумно сложно, и в тот момент, когда вы отказываетесь от устоявшихся практик, поддерживаемых экспертами в этой области, вы оказываетесь в пропасти и рискуете наихудшими условиями гонки. Я не являюсь ни экспертом в этой области, ни экспертом по вашему коду, поэтому я не могу судить так или иначе.

выдает предупреждение «ссылка на изменчивое поле не будет рассматриваться как изменчивое» Что мне следует думать об этом?

Вы должны понять, почему это является проблемой в целом. Это приведет к пониманию того, почему предупреждение неважно в данном конкретном случае.

Причина, по которой компилятор выдает это предупреждение, заключается в том, что пометка поля как изменчивого означает, что «это поле будет обновляться в нескольких потоках - не создавайте код, который кэширует значения этого поля, и убедитесь, что любое чтение или записи этого поля не «перемещаются вперед и назад во времени» из-за несогласованности кэша процессора ».

(Я предполагаю, что вы все это уже понимаете. Если у вас нет подробного понимания значения volatile и того, как оно влияет на семантику кэша процессора, то вы не понимаете, как это работает, и не должны использовать volatile. -свободные программы очень трудно получить правильно; убедитесь, что ваша программа правильная, потому что вы понимаете, как она работает, а не правильная случайно.)

Теперь предположим, что вы создали переменную, которая является псевдонимом изменчивого поля, передавая ссылка в это поле. Внутри вызываемого метода у компилятора нет никаких причин знать, что ссылка должна иметь изменчивую семантику! Компилятор с радостью сгенерирует код для метода, который не может реализовать правила для изменчивых полей, но переменная является изменчивым полем. Это может полностью разрушить вашу логику блокировки; всегда предполагается, что к изменчивому полю всегда осуществляется доступ с изменчивой семантикой. Иногда нет смысла рассматривать его как изменчивый, а иногда - нет; вы должны всегда быть согласованными, иначе вы не можете гарантировать согласованность при других доступах.

Таким образом, компилятор предупреждает, когда вы это делаете, потому что это, вероятно, полностью испортит вашу тщательно разработанную логику без блокировок.

Конечно, Interlocked.Exchange написан для ожидания изменчивого поля и выполнения правильных действий. Таким образом, предупреждение вводит в заблуждение. Я очень сожалею об этом; что мы должны были сделать, так это реализовать некий механизм, с помощью которого автор такого метода, как Interlocked.Exchange, мог бы поместить атрибут в метод, говорящий: «этот метод, который принимает ссылку, применяет изменчивую семантику к переменной, поэтому подавите предупреждение». Возможно, в будущей версии компилятора мы сделаем это.

173
ответ дан 24 November 2019 в 04:10
поделиться

Либо ваш коллега ошибается, либо он знает что-то, чего нет в спецификации языка C#.

5.5 Атомность ссылок на переменные:

"Читает и пишет следующее. типы данных атомарные: бул, чар, Байт, Сбайт, Короткий, Ушорт, Унт, Интр, float, и типы ссылок"

Таким образом, вы можете писать на волатильную ссылку без риска получить поврежденное значение.

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

9
ответ дан 24 November 2019 в 04:10
поделиться

Interlocked.Exchange

Устанавливает для переменной указанного типа T указанное значение и возвращает исходное значение в виде атомарной операции.

Он изменяет и возвращает исходное значение, это бесполезно, потому что вы хотите только изменить его, и, как сказал Гуффа, оно уже атомарно.

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

6
ответ дан 24 November 2019 в 04:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: