web-dev-qa-db-fra.com

Comment fonctionne l'attribut ThreadStatic?

Comment fonctionne [ThreadStatic] attribuer le travail? J'ai supposé que le compilateur émettrait un IL pour farcir/récupérer la valeur dans le TLS, mais regarder un désassemblage ne semble pas le faire à ce niveau.

En guise de suivi, que se passe-t-il si vous le mettez sur un membre non statique? Un développeur a commis cette erreur et le compilateur n'a même pas émis d'avertissement.

Mettre à jour

Réponse à la deuxième question ici: ThreadStatic modifié avec Stat C #

131
joshperry

La sémantique de l'implémentation de thread statique est inférieure au niveau IL, dans le compilateur jit .NET. Les compilateurs qui émettent en IL, comme VB.NET et C #, n'ont pas besoin de savoir quoi que ce soit sur Win32 TLS pour pouvoir émettre du code IL capable de lire et d'écrire une variable ayant l'attribut ThreadStatic. Pour autant que C # le sache, la variable n'a rien de spécial: il s'agit simplement d'un emplacement pour lire et écrire des éléments. Le fait qu'il ait un attribut n'a aucune incidence sur C #. C # a seulement besoin de savoir pour émettre des instructions de lecture ou d'écriture IL pour ce nom de symbole.

Le "travail lourd" est effectué par le CLR principal, responsable de la mise en œuvre de l’IL sur une architecture matérielle particulière.

Cela expliquerait également pourquoi le fait de placer l'attribut sur un symbole inapproprié (non statique) ne suscite aucune réaction du compilateur. Le compilateur ne sait pas quelle sémantique spéciale est requise par l'attribut. Les outils d'analyse de code tels que FX/Cop, cependant, devraient le savoir.

Une autre façon de voir les choses: CIL définit un ensemble d’étendues de stockage: stockage statique (global), stockage des membres et stockage en pile. TLS n'est pas sur cette liste, très probablement parce que TLS n'a pas besoin d'être sur cette liste. Si les instructions de lecture et d'écriture IL suffisent pour accéder à TLS lorsque le symbole est étiqueté avec un attribut TLS, pourquoi IL devrait-il avoir une représentation ou un traitement particulier pour TLS? Ce n'est pas nécessaire.

87
dthorpe

Comment fonctionne l'attribut [ThreadStatic]?

Vous pouvez penser que le champ marqué ThreadStatic est associé à un thread et que sa durée de vie est comparable à celle d'un thread.

Donc, dans le pseudocode, ThreadStatic est similaire (par la sémantique) à avoir une valeur-clé attachée à un thread:

Thread.Current["MyClass.myVariable"] = 1;
Thread.Current["MyClass.myvariable"] += 1;

mais la syntaxe est un peu plus simple:

class MyClass {
  [ThreadStatic]
  static int myVariable;
}
// .. then
MyClass.myVariable = 1;
MyClass.myVariable += 1;

que se passe-t-il si vous le mettez sur un membre non statique?

Je crois que c'est ignoré:

    class A {
        [ThreadStatic]
        public int a;
    }
    [Test]
    public void Try() {
        var a1 = new A();
        var a2 = new A();
        a1.a = 5;
        a2.a = 10;
        a1.a.Should().Be.EqualTo(5);
        a2.a.Should().Be.EqualTo(10);
    }

De plus, il est à noter que ThreadStatic ne nécessite aucun mécanisme de synchronisation par rapport aux champs statiques normaux (car l’état n’est pas partagé).

109

[ThreadStatic] crée des versions isolées de la même variable dans chaque thread.

Exemple:

[ThreadStatic] public static int i; // Declaration of the variable i with ThreadStatic Attribute.

public static void Main()
{
    new Thread(() =>
    {
        for (int x = 0; x < 10; x++)
        {
            i++;
            Console.WriteLine("Thread A: {0}", i); // Uses one instance of the i variable.
        }
    }).Start();

    new Thread(() =>
   {
       for (int x = 0; x < 10; x++)
       {
           i++;
           Console.WriteLine("Thread B: {0}", i); // Uses another instance of the i variable.
       }
   }).Start();
}
5
Rui Ruivo