Un’assegnazione di riferimento è protetta da thread?

Sto costruendo una cache multi-threaded in C #, che conterrà un elenco di oggetti Car:

public static IList Cars {get; private set;} 

Mi chiedo se è sicuro cambiare il riferimento in una discussione senza bloccarlo?

per esempio

 private static void Loop() { while (true) { Cars = GetFreshListFromServer(); Thread.Sleep(SomeInterval); } } 

Fondamentalmente si tratta di stabilire se assegnare un nuovo riferimento a Cars sia atomico o meno.

Se non lo è, dovrò ovviamente usare un campo privato per le mie macchine, e bloccare l’acquisizione e le impostazioni.

Sì, gli aggiornamenti di riferimento sono garantiti per essere atomici nelle specifiche del linguaggio.

5.5 Atomicità dei riferimenti variabili

Le letture e le scritture dei seguenti tipi di dati sono atomiche: bool, char, byte, sbyte, short, ushort, uint, int, float e reference. Inoltre, le letture e le scritture dei tipi di enum con un tipo sottostante nell’elenco precedente sono anche atomiche. Le letture e le scritture di altri tipi, inclusi i tipi lunghi, ulong, double e decimal, così come i tipi definiti dall’utente, non sono garantiti come atomici.

Tuttavia all’interno di un circuito chiuso potresti essere morso dalla cache del registro. Improbabile in questo caso, a meno che il metodo non sia in linea (il che potrebbe accadere). Personalmente aggiungerei il lock per renderlo semplice e prevedibile, ma anche volatile può aiutarti. E nota che la sicurezza del thread completo è molto più della semplice atomicità.

Nel caso di una cache, guarderei Interlocked.CompareExchange , personalmente, cioè cerco di aggiornare, ma se fallisce, rifare il lavoro da zero (partendo dal nuovo valore) e riprovare.

Nella risposta di @Marc Gravell, come indicato nel C # Language Spec 5.5, è importante sapere cosa si intende con il termine “tipo definito dall’utente”. Non ho trovato una chiara definizione per questo uso nella specifica del linguaggio C #. Nell’UML e nel linguaggio comune, una Classe è un’istanza di un Tipo. Ma nel contesto della C # Language Spec, il suo significato non è chiaro.

La sezione di riferimento del linguaggio Visual Basic “Tipi definiti dall’utente” (all’indirizzo https://msdn.microsoft.com/en-us/library/cec05s9z.aspx ) dice

“Versioni precedenti di Visual Basic supportano il tipo definito dall’utente (UDT). La versione corrente espande l’UDT in una struttura.”

quindi sembrerebbe che un tipo definito dall’utente sia una struttura, non una class.

Ma ….

In base alla “Guida alla programmazione C #” sezione “Tipi” ( https://msdn.microsoft.com/en-us/library/ms173104.aspx ):

“Un tipico programma C # utilizza i tipi dalla libreria di classi così come i tipi definiti dall’utente”

il che implica che una class è un tipo definito dall’utente. Successivamente, fornisce un esempio di “tipi definiti dall’utente complessi:”

MyClass myClass;

che significa “MyClass” è un tipo definito dall’utente. E più tardi dice:

“Ogni tipo nel CTS è definito come un tipo di valore o un tipo di riferimento, inclusi tutti i tipi personalizzati nella libreria di classi .NET Framework e anche i tipi definiti dall’utente .”

… il che implicherebbe che tutte le classi create da uno sviluppatore siano un “tipo definito dall’utente”.

E, infine, c’è questo articolo StackOverflow in cui il significato di questo termine è discusso in modo inconclusivo: come faccio a determinare se una proprietà è un tipo definito dall’utente in C #?

Pertanto, per essere sicuro, sono costretto a considerare tutte le Classi, sia quelle che creo che quelle trovate nel .Net Framework, tutte per essere definite dall’utente e quindi non thread safe per l’assegnazione, perché dice nel C # Sezione specifica della lingua 5.5:

Le letture e le scritture di … così come i tipi definiti dall’utente, non sono garantiti per essere atomici.

È spiacevole che un termine colloquiale sia usato in una specifica precisa come la specifica del linguaggio C #. A causa di questa ambiguità, per essere thread-safe, potrei scrivere un codice meno ottimale di quanto sarebbe ansible se risultasse che “Tipo definito dall’utente” non include le classi CLR.

Pertanto, chiedo ulteriori chiarimenti su questa risposta StackOverflow poiché la base attuale della risposta lascia questa significativa ambiguità. Allo stato attuale, la risposta alla domanda ” È un assegnamento di riferimento sicuro da thread? ” Sembra essere ” NO “.