ThreadStatic vs ThreadLocal <T>: ¿es genérico mejor que el atributo?

95

[ThreadStatic]se define usando atributo mientras que ThreadLocal<T>usa genérico. ¿Por qué se eligieron diferentes soluciones de diseño? ¿Cuáles son las ventajas y desventajas de utilizar atributos genéricos en lugar de en este caso?

usuario2341923
fuente
4
Ver reedcopsey.com/2009/11/12/… - Sin embargo , no veo qué tiene esto que ver con la reflexión ...
Jon Skeet

Respuestas:

112

Algo que la publicación del blog anotó en los comentarios no hace explícito, pero me parece muy importante, es que [ThreadStatic]no inicializa automáticamente las cosas para cada hilo. Por ejemplo, digamos que tiene esto:

[ThreadStatic]
private static int Foo = 42;

El primer hilo que usa esto se verá Fooinicializado en 42. Pero los hilos posteriores no lo harán. El inicializador funciona solo para el primer hilo. Entonces terminas teniendo que escribir código para verificar si está inicializado.

ThreadLocal<T> resuelve ese problema permitiéndole proporcionar una función de inicialización (como muestra el blog de Reed) que se ejecuta antes de la primera vez que se accede al elemento.

En mi opinión, no hay ninguna ventaja en usar en [ThreadStatic]lugar de ThreadLocal<T>.

Jim Mischel
fuente
20
Excepto quizás que ThreadLocal<T>esté disponible en .NET 4 y versiones posteriores, y el ThreadStaticatributo también está disponible en 3.5 y versiones posteriores.
Jeroen
2
Y si no está usando inicializadores para establecer el valor, sino que lo está estableciendo en algún momento posterior después de la inicialización, usar [ThreadStatic] es sintácticamente más limpio.
Pensamiento
9
Y excepto que ThreadLocal<T>implementa IDisposabley generalmente lo obliga a implementar IDisposabletambién, lo que obliga a las personas que llaman a deshacerse de usted y, por lo tanto, implementarlo IDisposabletambién ...
Stefan Steinegger
4
@StefanSteinegger: Sería muy cuidadoso al usar ThreadLocalo ThreadStaticcon subprocesos de grupo. Esos valores permanecerán durante toda la vida útil del subproceso del grupo, no solo para la tarea que le asigne. Eso puede causarle problemas de formas bastante no obvias. Consulte stackoverflow.com/questions/561518/… y preguntas similares para obtener más información.
Jim Mischel
3
¿No debería declararse también el campo del ejemplo static? Ver msdn.microsoft.com/en-us/library/…
entheh
39

ThreadStatic Initialize solo en el primer subproceso, ThreadLocal Initialize para cada subproceso. A continuación se muestra la demostración 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();
    }

ingrese la descripción de la imagen aquí

marai
fuente
15

La idea principal detrás de ThreadStatic es mantener una copia separada de la variable para cada hilo .

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

En el fragmento anterior, tenemos una copia separada de valuepara cada hilo, incluido el hilo principal.

ingrese la descripción de la imagen aquí

Por lo tanto, una variable ThreadStatic se inicializará a su valor predeterminado en otros subprocesos, excepto en el subproceso en el que se creó.

Si queremos inicializar la variable en cada hilo a nuestra manera, use ThreadLocal.

Sanjeev
fuente
1
Y el artículo completo se puede encontrar aquí .
Daniel Dušek