Тут є численні запитання. Розглядаючи їх по одному:
Призначення посилань є атомним, тому для чого потрібен Interlocked.Exchange (ref об'єкт, об'єкт)?
Призначення довідників є атомним. Interlocked.Exchange не виконує лише призначення посилань. Він робить зчитування поточного значення змінної, приховує старе значення і присвоює нове значення змінній, все як атомна операція.
мій колега сказав, що на деяких платформах не гарантується, що присвоєння довідок є атомним. Правильний був мій колега?
Ні. Призначення посилань гарантується атомним на всіх платформах .NET.
Мій колега міркує з помилкових приміщень. Чи означає це, що їхні висновки невірні?
Не обов'язково. Ваш колега міг би дати вам гарну пораду з поганих причин. Можливо, є якась інша причина, чому ви повинні використовувати Interlocked.Exchange. Програмування без блокувань є шалено важким, і в момент, коли ви відходите від усталених практик, що застосовуються фахівцями в цій галузі, ви перебуваєте в бур'яні і ризикуєте найгіршими умовами змагань. Я не є ані експертом у цій галузі, ані експертом у вашому коді, тому не можу виносити судження так чи інакше.
створює попередження: "посилання на мінливе поле не трактуватиметься як мінливе". Що я повинен думати з цього приводу?
Ви повинні зрозуміти, чому це взагалі проблема. Це призведе до розуміння того, чому попередження є неважливим у даному конкретному випадку.
Причина, через яку компілятор дає це попередження, полягає в тому, що маркування поля мінливим означає "це поле буде оновлено в декількох потоках - не створюйте жодного коду, який кешує значення цього поля, і переконайтеся, що будь-який читає чи записує це поле не "переміщується вперед та назад" через невідповідність кешу процесора ".
(Я припускаю, що ви все це вже розумієте. Якщо ви не маєте детального розуміння значення летючого та як це впливає на семантику кешу процесора, ви не розумієте, як це працює і не слід використовувати летючі. Програми без блокування дуже важко отримати право; переконайтеся, що ваша програма правильна, тому що ви розумієте, як вона працює, не випадково.)
Тепер припустимо, що ви зробите змінну, яка є псевдонімом летючого поля, передавши посилання на це поле. Всередині названого методу компілятор не має жодної причини знати, що у посиланні має бути мінлива семантика! Компілятор бадьоро генерує код для методу, який не реалізує правила для летючих полів, але змінна - це мінливе поле. Це може повністю зруйнувати вашу логіку без блокування; припущення завжди полягає в тому, що до летючого поля завжди звертається летюча семантика. Немає сенсу трактувати це як мінливий іноді, а не інший час; ви завжди повинні бути послідовними, інакше ви не можете гарантувати послідовність щодо інших доступу.
Тому компілятор попереджає, коли ви це зробите, адже це, ймовірно, повністю зіпсує вашу ретельно розроблену логіку без блокування.
Звичайно, Interlocked.Exchange буде написано очікувати летюча поле і робити правильні речі. Тому попередження є оманливим. Я дуже шкодую про це; що ми повинні були зробити, це реалізувати якийсь механізм, за допомогою якого автор такого методу, як Interlocked.Exchange міг би поставити атрибут методу, що говорить "цей метод, який приймає ref, примушує мінливу семантику змінної, тому придушуйте попередження". Можливо, у майбутній версії компілятора ми це зробимо.