ThreadStatic vs ThreadLocal : è generico meglio dell’attributo?

[ThreadStatic] viene definito utilizzando l’attributo mentre ThreadLocal utilizza generico. Perché sono state scelte diverse soluzioni di design? Quali sono i vantaggi e gli svantaggi dell’utilizzo degli attributi over generici in questo caso?

Qualcosa che il post del blog ha notato nei commenti non rende esplicito, ma trovo che sia molto importante, è che [ThreadStatic] non inizializza automaticamente le cose per ogni thread. Ad esempio, dì di avere questo:

 [ThreadStatic] private static int Foo = 42; 

Il primo thread che usa questo mostrerà Foo inizializzato a 42 . Ma i fili successivi non lo faranno. L’inizializzatore funziona solo per il primo thread. Quindi finisci per dover scrivere codice per verificare se è inizializzato.

ThreadLocal risolve questo problema consentendo di fornire una funzione di inizializzazione (come mostra il blog di Reed) che viene eseguita prima della prima volta che si accede all’elemento.

A mio parere, non c’è alcun vantaggio nell’usare [ThreadStatic] invece di ThreadLocal .

ThreadStatic Inizializza solo sul primo thread, ThreadLocal Initialize per ogni thread. Di seguito è riportata la semplice dimostrazione:

  public static ThreadLocal _threadlocal = new ThreadLocal(() => { return Thread.CurrentThread.ManagedThreadId; }); public static void Main() { new Thread(() => { for (int x = 0; x < _threadlocal.Value; x++) { Console.WriteLine("First Thread: {0}", x); } }).Start(); new Thread(() => { for (int x = 0; x < _threadlocal.Value; x++) { Console.WriteLine("Second Thread: {0}", x); } }).Start(); Console.ReadKey(); } 

inserisci la descrizione dell'immagine qui

L’idea principale dietro ThreadStatic è di mantenere una copia separata della variabile per ogni thread .

 class Program { [ThreadStatic] static int value = 10; static void Main(string[] args) { value = 25; Task t1 = Task.Run(() => { value++; Console.WriteLine("T1: " + value); }); Task t2 = Task.Run(() => { value++; Console.WriteLine("T2: " + value); }); Task t3 = Task.Run(() => { value++; Console.WriteLine("T3: " + value); }); Console.WriteLine("Main Thread : " + value); Task.WaitAll(t1, t2, t3); Console.ReadKey(); } } 

Nel frammento di cui sopra, abbiamo una copia separata del value per ogni thread, incluso il thread principale.

inserisci la descrizione dell'immagine qui

Quindi, una variabile ThreadStatic verrà inizializzata sul valore predefinito su altri thread, ad eccezione del thread su cui è stato creato.

Se vogliamo inizializzare la variabile su ogni thread a modo nostro, usa ThreadLocal.