web-dev-qa-db-fra.com

Les variables thread_local C ++ 11 sont-elles automatiquement statiques?

Y a-t-il une différence entre ces deux segments de code:

void f() {
    thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

et

void f() {
    static thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

Backstory: à l'origine, j'avais un vecteur STATIC V (pour contenir certaines valeurs intermédiaires, il est effacé à chaque fois que j'entre dans la fonction) et un programme à un seul thread. Je veux transformer le programme en un multithreading, donc je dois en quelque sorte me débarrasser de ce modificateur statique. Mon idée est de transformer chaque statique en thread_local et de ne pas vous soucier d'autre chose? Cette approche peut-elle se retourner?

69
Zuza

Selon la norme C++

Lorsque thread_local est appliqué à une variable de portée de bloc, le spécificateur de classe de stockage statique est implicite s'il n'apparaît pas explicitement

Cela signifie donc que cette définition

void f() {
    thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

est équivalent à

void f() {
    static thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

Cependant, une variable statique est pas la même chose qu'une variable thread_local.

1 Toutes les variables déclarées avec le mot clé thread_local ont une durée de stockage des threads. Le stockage de ces entités doit durer pendant la durée du thread dans lequel elles sont créées. Il existe un objet ou une référence distincte par thread, et l'utilisation du nom déclaré fait référence à l'entité associée au thread actuel

Pour distinguer ces variables, la norme introduit un nouveau terme durée de stockage des threads ainsi que la durée de stockage statique.

77
Vlad from Moscow

Oui, le "stockage local de threads" est très similaire au "global" (ou "stockage statique"), seulement qu'au lieu de "durée de tout le programme" vous avez "durée de tout le thread". Ainsi, une variable locale de bloc local de thread est initialisée la première fois que le contrôle passe par sa déclaration, mais séparément dans chaque thread, et elle est détruite à la fin du thread.

16
Kerrek SB

Lorsqu'il est utilisé avec thread_local, static est impliqué dans la portée de bloc (voir la réponse de @ Vlad), requis pour un membre de la classe; Je suppose que cela signifie un lien pour la portée de l'espace de noms.

Par 9.2/6:

Dans une définition de classe, un membre ne doit pas être déclaré avec le thread_local storage-class-specifier sauf s'il est également déclaré statique

Pour répondre à la question d'origine:

Les variables thread_local C++ 11 sont-elles automatiquement statiques?

Il n'y a pas d'autre choix, sauf pour les variables de portée d'espace de noms.

Y a-t-il une différence entre ces deux segments de code:

Non.

6
vehsakul

Le stockage local de thread est statique mais il se comporte très différemment du stockage statique simple.

Lorsque vous déclarez une variable statique, il y a exactement une instance de la variable. Le compilateur/système d'exécution garantit qu'il sera initialisé pour vous quelque temps avant que vous ne l'utilisiez réellement, sans spécifier exactement quand (certains détails sont omis ici.)

C++ 11 garantit que cette initialisation sera sécurisée pour les threads, mais avant C++ 11, cette sécurité des threads n'était pas garantie. Par exemple

static X * pointer = new X;

peut provoquer une fuite d'instances de X si plusieurs threads atteignent le code d'initialisation statique en même temps.

Lorsque vous déclarez un thread de variable local, il existe potentiellement de nombreuses instances de la variable. Vous pouvez les considérer comme faisant partie d'une carte indexée par thread-id. Cela signifie que chaque thread voit sa propre copie de la variable.

Encore une fois, si la variable est initialisée, le système compilateur/runtime garantit que cette initialisation se produira avant l'utilisation des données et que l'initialisation se produira pour chaque thread qui utilise la variable. Le compilateur garantit également que l'initiation sera thread-safe.

Les garanties de sécurité des threads signifient qu'il peut y avoir beaucoup de code en arrière-plan pour que la variable se comporte comme vous vous y attendez - d'autant plus que le compilateur n'a aucun moyen de savoir à l'avance exactement combien de threads existent dans votre programme et combien d'entre eux toucheront la variable locale du thread.

4
Dale Wilson