ThreadStatic vs ThreadLocal <T>: Ist generisch besser als Attribut?


Antworten:


110

Etwas, das der Blog-Beitrag in den Kommentaren nicht explizit macht, aber ich finde es sehr wichtig, dass [ThreadStatic]es nicht automatisch Dinge für jeden Thread initialisiert. Angenommen, Sie haben Folgendes:

[ThreadStatic]
private static int Foo = 42;

Der erste Thread, der dies verwendet, wird auf Fooinitialisiert 42. Aber nachfolgende Threads werden nicht. Der Initialisierer funktioniert nur für den ersten Thread. Am Ende müssen Sie also Code schreiben, um zu überprüfen, ob er initialisiert ist.

ThreadLocal<T> Behebt dieses Problem, indem Sie eine Initialisierungsfunktion (wie Reeds Blog zeigt) bereitstellen, die vor dem ersten Zugriff auf das Element ausgeführt wird.

Meiner Meinung nach hat die Verwendung von [ThreadStatic]statt keinen Vorteil ThreadLocal<T>.


20
Außer vielleicht ThreadLocal<T>ist dies in .NET 4 und höher verfügbar, und das ThreadStaticAttribut ist auch in Version 3.5 und darunter verfügbar.
Jeroen

2
Wenn Sie den Wert nicht mit Initialisierern festlegen, sondern ihn zu einem späteren Zeitpunkt nach der Initialisierung festlegen, ist die Verwendung von [ThreadStatic] syntaktisch sauberer.
Dachte

9
Und außer das ThreadLocal<T>implementiert IDisposableund zwingt Sie normalerweise auch zur Implementierung IDisposable, was Ihre Anrufer dazu zwingt, Sie zu entsorgen und daher auch zu implementieren IDisposable...
Stefan Steinegger

4
@StefanSteinegger: Ich würde sehr vorsichtig mit ThreadLocaloder ThreadStaticmit Pool-Threads sein. Diese Werte bleiben während der gesamten Lebensdauer des Pool-Threads erhalten, nicht nur für die Aufgabe, die Sie ihm zuweisen. Das kann Ihnen auf ziemlich nicht offensichtliche Weise Probleme bereiten. Weitere Informationen finden Sie unter stackoverflow.com/questions/561518/… und ähnlichen Fragen.
Jim Mischel

3
Sollte das Feld im Beispiel nicht auch deklariert werden static? Siehe msdn.microsoft.com/en-us/library/…
am

39

ThreadStatic Initialize nur für den ersten Thread, ThreadLocal Initialize für jeden Thread. Unten ist die einfache Demonstration:

    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();
    }

Geben Sie hier die Bildbeschreibung ein


14

Die Hauptidee hinter ThreadStatic besteht darin, für jeden Thread eine separate Kopie der Variablen zu verwalten .

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();
        }
    }

Im obigen Snippet haben wir valuefür jeden Thread eine separate Kopie , einschließlich des Hauptthreads.

Geben Sie hier die Bildbeschreibung ein

Daher wird eine ThreadStatic-Variable in anderen Threads mit Ausnahme des Threads, in dem sie erstellt wurde, auf ihren Standardwert initialisiert.

Wenn wir die Variable für jeden Thread auf unsere eigene Weise initialisieren möchten, verwenden Sie ThreadLocal.


1
Den vollständigen Artikel finden Sie hier .
Daniel Dušek
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.