Здесь возникает множество вопросов. Рассматривая их по одному:
присвоение ссылки является атомарным, так зачем нужен Interlocked.Exchange (ref Object, Object)?
Назначение ссылок является атомарным. Interlocked.Exchange выполняет не только присвоение ссылок. Он считывает текущее значение переменной, прячет старое значение и присваивает переменной новое значение, все как атомарная операция.
мой коллега сказал, что на некоторых платформах не гарантируется, что присвоение ссылок является атомарным. Прав ли был мой коллега?
Нет. Назначение ссылок гарантированно атомарно на всех платформах .NET.
Мой коллега исходит из ложных предпосылок. Означает ли это, что их выводы неверны?
Не обязательно. Ваш коллега может давать вам хороший совет по плохим причинам. Возможно, есть другая причина, по которой вам следует использовать Interlocked.Exchange. Программирование без блокировок безумно сложно, и в тот момент, когда вы отказываетесь от устоявшихся практик, поддерживаемых экспертами в этой области, вы оказываетесь в пропасти и рискуете наихудшими условиями гонки. Я не являюсь ни экспертом в этой области, ни экспертом по вашему коду, поэтому я не могу судить так или иначе.
выдает предупреждение "ссылка на изменчивое поле не будет рассматриваться как изменчивое" Что я должен думать об этом?
Вы должны понимать, почему это вообще проблема. Это приведет к пониманию того, почему предупреждение неважно в данном конкретном случае.
Причина, по которой компилятор выдает это предупреждение, заключается в том, что пометка поля как изменчивого означает, что «это поле будет обновляться в нескольких потоках - не создавайте никакого кода, который кэширует значения этого поля, и убедитесь, что любое чтение или запись это поле не «перемещается вперед и назад во времени» из-за несогласованности кэша процессора ».
(Я предполагаю, что вы все это уже понимаете. Если у вас нет подробного понимания значения volatile и того, как оно влияет на семантику кеш-памяти процессора, то вы не понимаете, как это работает, и не должны использовать volatile. Программы без блокировки очень сложно сделать правильно; убедитесь, что ваша программа правильная, потому что вы понимаете, как она работает, а не случайно.)
Теперь предположим, что вы создали переменную, которая является псевдонимом изменчивого поля, передав ссылку на это поле. Внутри вызываемого метода у компилятора нет никаких причин знать, что ссылка должна иметь изменчивую семантику! Компилятор с радостью сгенерирует код для метода, который не может реализовать правила для изменчивых полей, но переменная является изменчивым полем. Это может полностью разрушить вашу логику блокировки; всегда предполагается, что доступ к изменчивому полю всегда осуществляется с изменчивой семантикой. Иногда нет смысла рассматривать его как изменчивый, а иногда - нет; вы должны всегда быть последовательными, иначе вы не сможете гарантировать согласованность при других доступах.
Поэтому компилятор предупреждает, когда вы это делаете, потому что это, вероятно, полностью испортит вашу тщательно разработанную логику блокировки.
Конечно, Interlocked.Exchange будет написано ожидать летучее поле и делать правильные вещи. Следовательно, предупреждение вводит в заблуждение. Я очень сожалею об этом; что мы должны были сделать, так это реализовать какой-то механизм, с помощью которого автор такого метода, как Interlocked.Exchange, мог бы поместить атрибут в метод, говорящий, что «этот метод, который принимает ref, применяет изменчивую семантику к переменной, поэтому подавите предупреждение». Возможно, в будущей версии компилятора мы сделаем это.
var myresult = await Task.Factory.CreateNew(() => MyWork(exclusivelyLocalStuffOrValueTypeOrCopy));
.Либо ваш коллега ошибается, либо он знает то, чего не знает спецификация языка C #.
5.5 Атомарность ссылок на переменные :
Таким образом, вы можете писать в изменчивую ссылку без риска получить поврежденное значение.
Конечно, вы должны быть осторожны с тем, как вы решаете, какой поток должен получать новые данные, чтобы свести к минимуму риск того, что это сделает более одного потока одновременно.
источник
Блокировано. Обмен <T>
Он изменяет и возвращает исходное значение, это бесполезно, потому что вы хотите только изменить его, и, как сказал Гуффа, оно уже атомарно.
Если профилировщик не доказал, что он является узким местом в вашем приложении, вам следует рассмотреть возможность снятия блокировок, так легче понять и доказать, что ваш код правильный.
источник
Iterlocked.Exchange()
не просто атомарен, он также заботится о видимости памяти:Синхронизация и многопроцессорные проблемы
Это означает, что помимо атомарности он гарантирует, что:
источник