Ci sono numerose domande qui. Considerandoli uno alla volta:
l'assegnazione dei riferimenti è atomica, quindi perché è necessario Interlocked.Exchange (ref Object, Object)?
L'assegnazione dei riferimenti è atomica. Interlocked.Exchange non fa solo l'assegnazione dei riferimenti. Effettua una lettura del valore corrente di una variabile, nasconde il vecchio valore e assegna il nuovo valore alla variabile, il tutto come un'operazione atomica.
il mio collega ha detto che su alcune piattaforme non è garantito che l'assegnazione dei riferimenti sia atomica. Il mio collega aveva ragione?
No. L'assegnazione dei riferimenti è garantita come atomica su tutte le piattaforme .NET.
Il mio collega ragiona da false premesse. Ciò significa che le loro conclusioni non sono corrette?
Non necessariamente. Il tuo collega potrebbe darti buoni consigli per cattivi motivi. Forse c'è qualche altro motivo per cui dovresti usare Interlocked.Exchange. La programmazione senza blocchi è incredibilmente difficile e nel momento in cui ti allontani da pratiche consolidate sposate da esperti del settore, sei tra le erbacce e rischia il peggior tipo di condizioni di gara. Non sono né un esperto in questo campo né un esperto del tuo codice, quindi non posso esprimere un giudizio in un modo o nell'altro.
produce un avviso "un riferimento a un campo volatile non verrà trattato come volatile" Cosa dovrei pensare al riguardo?
Dovresti capire perché questo è un problema in generale. Ciò porterà alla comprensione del motivo per cui l'avvertimento non è importante in questo caso particolare.
Il motivo per cui il compilatore fornisce questo avviso è perché contrassegnare un campo come volatile significa "questo campo verrà aggiornato su più thread: non generare alcun codice che memorizzi nella cache i valori di questo campo e assicurati che qualsiasi lettura o scrittura di questo campo non viene "spostato avanti e indietro nel tempo" tramite incongruenze della cache del processore. "
(Presumo che tu abbia già capito tutto questo. Se non hai una comprensione dettagliata del significato di volatile e di come influisce sulla semantica della cache del processore, allora non capisci come funziona e non dovresti usare volatile. Programmi senza blocco sono molto difficili da mettere a punto; assicurati che il tuo programma sia giusto perché capisci come funziona, non giusto per caso.)
Supponiamo ora di creare una variabile che è un alias di un campo volatile passando un riferimento a quel campo. All'interno del metodo chiamato, il compilatore non ha alcun motivo per sapere che il riferimento deve avere una semantica volatile! Il compilatore genererà allegramente il codice per il metodo che non riesce a implementare le regole per i campi volatili, ma la variabile è un campo volatile. Questo può rovinare completamente la tua logica senza blocco; il presupposto è sempre che un campo volatile sia sempre accessibile con semantica volatile. Non ha senso trattarlo come volatile a volte e non altre volte; devi essere sempre coerente altrimenti non puoi garantire la coerenza su altri accessi.
Pertanto, il compilatore avvisa quando lo fai, perché probabilmente rovinerà completamente la tua logica senza blocchi sviluppata con cura.
Ovviamente, Interlocked.Exchange è scritto per aspettarsi un campo volatile e fare la cosa giusta. L'avvertimento è quindi fuorviante. Me ne rammarico molto; quello che avremmo dovuto fare è implementare un meccanismo in base al quale un autore di un metodo come Interlocked.Exchange potrebbe mettere un attributo sul metodo dicendo "questo metodo che richiede un ref impone la semantica volatile sulla variabile, quindi sopprimi l'avvertimento". Forse in una futura versione del compilatore lo faremo.