ThreadStatic vs ThreadLocal <T>: le générique est-il meilleur que l'attribut?


95

[ThreadStatic]est défini à l'aide de l'attribut tandis que ThreadLocal<T>utilise générique. Pourquoi différentes solutions de conception ont-elles été choisies? Quels sont les avantages et les inconvénients de l'utilisation des attributs génériques dans ce cas?


4
Voir reedcopsey.com/2009/11/12 / ... - Je ne vois pas ce que cela a à voir avec la réflexion ...
Jon Skeet

Réponses:


112

Ce que l'article de blog noté dans les commentaires ne rend pas explicite, mais je trouve très important, c'est que cela [ThreadStatic]n'initialise pas automatiquement les choses pour chaque fil. Par exemple, disons que vous avez ceci:

[ThreadStatic]
private static int Foo = 42;

Le premier thread qui l'utilise verra Fooinitialisé à 42. Mais les fils suivants ne le seront pas. L'initialiseur fonctionne uniquement pour le premier thread. Vous finissez donc par devoir écrire du code pour vérifier s'il est initialisé.

ThreadLocal<T> résout ce problème en vous permettant de fournir une fonction d'initialisation (comme le montre le blog de Reed) qui est exécutée avant le premier accès à l'élément.

À mon avis, il n'y a aucun avantage à utiliser [ThreadStatic]au lieu de ThreadLocal<T>.


20
Sauf peut-être que ThreadLocal<T>c'est disponible dans .NET 4 et plus, et l' ThreadStaticattribut est également disponible dans 3.5 et ci-dessous.
Jeroen

2
Et si vous n'utilisez pas d'initialiseurs pour définir la valeur, mais que vous la définissez plus tard après l'initialisation, l'utilisation de [ThreadStatic] est syntaxiquement plus propre.
Pensée le

9
Et sauf que cela ThreadLocal<T>implémente IDisposableet vous oblige généralement à implémenter IDisposableégalement, ce qui oblige vos appelants à vous éliminer et donc à implémenter IDisposableégalement ...
Stefan Steinegger

4
@StefanSteinegger: Je serais très prudent en utilisant ThreadLocalou ThreadStaticavec des threads de pool. Ces valeurs resteront pendant toute la durée de vie du thread de pool, pas seulement pour la tâche que vous lui attribuez. Cela peut vous causer des problèmes de manière assez peu évidente. Voir stackoverflow.com/questions/561518/… et des questions similaires pour plus d'informations.
Jim Mischel

3
Le champ de l'exemple ne devrait-il pas également être déclaré static? Voir msdn.microsoft.com/en-us/library/…
entheh

39

ThreadStatic Initialize uniquement sur le premier thread, ThreadLocal Initialize pour chaque thread. Voici la démonstration simple:

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

entrez la description de l'image ici


15

L'idée principale derrière ThreadStatic est de conserver une copie séparée de la variable pour chaque 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();
        }
    }

Dans l'extrait de code ci-dessus, nous avons une copie distincte de valuepour chaque thread, y compris le thread principal.

entrez la description de l'image ici

Ainsi, une variable ThreadStatic sera initialisée à sa valeur par défaut sur d'autres threads à l'exception du thread sur lequel elle est créée.

Si nous voulons initialiser la variable sur chaque thread à notre manière, utilisez ThreadLocal.


1
Et l'article complet peut être trouvé ici .
Daniel Dušek
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.