Qui ci sono numerose domande. Considerandoli uno alla volta:
l'assegnazione di riferimento è atomica, quindi perché è necessario Interlocked.Exchange (oggetto ref, oggetto)?
L'assegnazione di riferimento è atomica. Interlocked.Exchange non esegue solo assegnazioni di riferimento. Fa una lettura del valore corrente di una variabile, ripara il vecchio valore e assegna il nuovo valore alla variabile, tutto come un'operazione atomica.
il mio collega ha affermato che su alcune piattaforme non è garantito che l'assegnazione di riferimento sia atomica. La mia collega era corretta?
No. L'assegnazione di riferimento è garantita per essere atomica su tutte le piattaforme .NET.
Il mio collega ragiona da premesse sbagliate. Ciò significa che le loro conclusioni non sono corrette?
Non necessariamente. Il tuo collega potrebbe darti un buon consiglio per cattive ragioni. Forse c'è qualche altra ragione per cui dovresti usare Interlocked.Exchange. La programmazione senza blocco è faticosamente difficile e nel momento in cui ti allontani da pratiche consolidate sposate da esperti del settore, sei fuori dalle erbacce e rischi 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 avviso "un riferimento a un campo volatile non sarà trattato come volatile" Che cosa dovrei pensare a questo?
Si dovrebbe capire perché questo è un problema in generale. Ciò porterà a capire perché 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 memorizza nella cache i valori di questo campo e assicurarsi che qualsiasi le letture o le scritture di questo campo non vengono "spostate avanti e indietro nel tempo" tramite incoerenze nella cache del processore. "
(Presumo che tu abbia già capito tutto questo Se non hai una conoscenza dettagliata del significato di volatile e di come influisce sulla semantica della cache del processore, allora non capisci come funziona e non dovrebbe essere volatile. I programmi di blocco sono molto difficili da ottenere, assicurati che il tuo programma sia corretto perché capisci come funziona, non per errore.)
Ora supponiamo di creare una variabile che è un alias di un campo volatile di passando un riferimento a quel campo. All'interno del metodo chiamato, il compilatore non ha alcuna ragione 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. Ciò può distruggere completamente la logica lock-free; l'ipotesi è sempre che un campo volatile sia sempre a a cui si accede con una semantica volatile. Non ha senso trattarlo come volatile a volte e non altre volte; devi sempre essere coerente altrimenti non puoi garantire la coerenza su altri accessi.
Pertanto, il compilatore avverte quando si esegue questa operazione, poiché probabilmente sta danneggiando completamente la logica lock-free attentamente sviluppata.
Naturalmente, Interlocked.Exchange è scritto per aspettarsi un campo volatile e fare la cosa giusta. L'avvertimento è quindi fuorviante. Mi dispiace molto; ciò che dovremmo fare è implementare un meccanismo in base al quale un autore di un metodo come Interlocked.Exchange potrebbe inserire un attributo nel metodo che dice "questo metodo che prende un riferimento per forzare la semantica volatile sulla variabile, quindi sopprimiamo l'avviso".Forse in una versione futura del compilatore lo faremo.
grazie! la migliore risposta di sempre! –
Da quello che ho sentito Interlocked.Exchange garantisce anche che venga creata una barriera di memoria. Quindi se per esempio create un nuovo oggetto, quindi assegnate un paio di proprietà e quindi memorizzate l'oggetto in un altro riferimento senza usare Interlocked.Exchange, il compilatore potrebbe rovinare l'ordine di quelle operazioni, rendendo così l'accesso al secondo riferimento non thread- sicuro. È davvero così? Ha senso usare Interlocked.Exchange è quel tipo di scenari? – Mike
@ Mike: Quando si tratta di ciò che si può osservare nelle situazioni multithreading a bassa chiusura, sono ignorante come il prossimo. La risposta probabilmente varierà da processore a processore. Dovresti indirizzare la tua domanda a un esperto o leggere sull'argomento se ti interessa. Il libro di Joe Duffy e il suo blog sono buoni punti di partenza.La mia regola: non usare il multithreading. Se è necessario, utilizzare strutture di dati immutabili. Se non puoi, usa le serrature. Solo quando * devi * avere dati mutabili senza blocchi, dovresti considerare le tecniche di blocco basso. –