ThreadStatic vs ThreadLocal <T>: generico è meglio dell'attributo?


Risposte:


112

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

[ThreadStatic]
private static int Foo = 42;

Il primo thread che utilizza questo verrà Fooinizializzato a 42. Ma i thread successivi non lo faranno. L'inizializzatore funziona solo per il primo thread. Quindi finisci per dover scrivere codice per verificare se è inizializzato.

ThreadLocal<T> risolve il problema consentendo di fornire una funzione di inizializzazione (come mostra il blog di Reed) che viene eseguita prima del primo accesso all'elemento.

A mio parere, non vi è alcun vantaggio nell'usare al [ThreadStatic]posto di ThreadLocal<T>.


20
Tranne forse che ThreadLocal<T>è disponibile in .NET 4 e versioni successive e l' ThreadStaticattributo è disponibile anche in 3.5 e versioni precedenti.
Jeroen

2
E se non stai usando gli inizializzatori per impostare il valore, ma lo stai invece impostando in un momento successivo dopo l'inizializzazione, l'uso di [ThreadStatic] è sintatticamente più pulito.
Pensiero

9
E tranne che ThreadLocal<T>implementa IDisposablee di solito ti costringe a implementare IDisposableanche tu , il che costringe i tuoi chiamanti a sbarazzarti e quindi implementare IDisposableanche tu ...
Stefan Steinegger

4
@StefanSteinegger: starei molto attento nell'usare ThreadLocalo ThreadStaticcon i thread del pool. Questi valori rimarranno per l'intera durata del thread del pool, non solo per l'attività assegnata. Ciò può causare problemi in modi piuttosto non ovvi. Vedi stackoverflow.com/questions/561518/… e domande simili per maggiori informazioni.
Jim Mischel

3
Non dovrebbe essere dichiarato anche il campo nell'esempio static? Vedere msdn.microsoft.com/en-us/library/...
entheh

39

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

    public static ThreadLocal<int> _threadlocal =
        new ThreadLocal<int>(() =>
        {
            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 qui la descrizione dell'immagine


15

L'idea principale alla base di ThreadStatic è 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();
        }
    }

Nello snippet sopra, abbiamo una copia separata di valueper ogni thread, incluso il thread principale.

inserisci qui la descrizione dell'immagine

Quindi, una variabile ThreadStatic verrà inizializzata al suo valore predefinito su altri thread eccetto il thread su cui è stata creata.

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


1
E l'articolo completo può essere trovato qui .
Daniel Dušek
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.