Ce qui ne l'thread_local moyenne en C++11?
Je suis confondue avec la description de thread_local
en C++11. Ma compréhension est, chaque thread a copie unique de variables locales à une fonction. La global/variables statiques peuvent être consultées par tous les threads (éventuellement accès synchronisé à l'aide des verrous). Et le thread_local
variables sont visibles pour tous les threads, mais ne peut que modifié par le thread pour lequel ils sont définis? Est-il correct?
Vous devez vous connecter pour publier un commentaire.
Locale de Thread durée de stockage est un terme utilisé pour se référer à des données qui est en apparence globale ou statique de la durée de stockage (du point de vue des fonctions de l'utiliser), mais en réalité, il existe un exemplaire par thread.
Qu'il ajoute à l'automatique en cours (cours bloc/de fonction), statique (qui n'existe que pour la durée du programme) et dynamique (il existe sur le tas entre l'allocation et la libération).
Quelque chose qui est thread-local est amenés à l'existence, à la création de threads et éliminés lorsque le thread s'arrête.
Quelques exemples suivre.
Penser à un générateur de nombre aléatoire où la graine doit être maintenu sur une base par thread. À l'aide d'un fil-de semences locales qui signifie que chaque thread possède sa propre séquence des nombres aléatoires, indépendantes des autres threads.
Si votre semence est une variable locale dans la fonction aléatoire, il serait initialisé à chaque fois que vous l'avez appelé, vous donnant le même nombre à chaque fois. Si c'était un mondial, fils d'interférer les uns avec les autres séquences.
Un autre exemple est quelque chose comme
strtok
où la tokenisation état est stocké sur un fil spécifique. De cette façon, un seul thread peut être sûr que les autres threads ne pas bousiller son tokenisation efforts, tout en étant capable de maintenir l'état sur les appels multiples àstrtok
- ce fondamentalement rendstrtok_r
(la version thread-safe) redondant.Ces deux exemples permettent de le thread variable locale d'exister dans la fonction qui l'utilise. En pré-threaded code, ce serait tout simplement une statique de la durée de stockage de la variable dans la fonction. Pour les threads, c'est modifié au fil local de stockage durée.
Encore un autre exemple serait quelque chose comme
errno
. Vous ne voulez pas des threads séparés modifianterrno
après que l'un de vos appels échoue, mais, avant, vous pouvez vérifier la variable, et pourtant vous ne voulez une copie par thread.Ce site a une description raisonnable de différentes durée de stockage des prescripteurs.
strtok
suggestion!strtok
.strtok
est brisé, même dans un seul thread de l'environnement.r
est l'acronyme de "re-venu", qui n'a rien à voir avec la sécurité des threads. Il est vrai que vous pouvez faire certaines choses fonctionnent fil en toute sécurité avec du fil de stockage local, mais vous ne pouvez pas les faire ré-entrant.strtok
devrait en appeler d'autres fonctions.while (something) { char *next = strtok(whatever); someFunction(next); // someFunction calls strtok }
strtok
des séquences dans un thread; - dire, si vous êtes le traitement de deux cordes en même temps. C'est là que le réentrant variantes venir dans maniable (plus c'est plus propre --- non globales sont accessibles).thread_local object
appelle sa deallocator à la fin de la discussion ?thread_local
Allocateur de l'objet qui pourrait être utilisé pour allouer de la mémoire avec de nouvelles/le placement de nouveaux quoi que ce soit sur le tas. En d'autres termes, les différentes mémoire allouée par thread.Lorsque vous déclarez une variable
thread_local
puis chaque thread possède sa propre copie. Lorsque vous le désigner par son nom, puis la copie associés avec le thread courant est utilisé. par exemple,Ce code de sortie "2349", "3249", "4239", "4329", "2439" ou "3429", mais jamais rien d'autre. Chaque thread possède sa propre copie de
i
, qui est affecté, incrémenté puis imprimé. Le thread en cours d'exécutionmain
a également sa propre copie, ce qui est attribué au début et puis à gauche inchangé. Ces copies sont entièrement indépendants, et chacun a une adresse différente.C'est seulement la nom qui est spécial à cet égard --- si vous prenez l'adresse d'un
thread_local
variable, alors vous avez juste normal d'un pointeur vers un objet normal, que vous pouvez passer librement entre les threads. par exemple,Depuis l'adresse de
i
est passé à la fonction de thread, puis la copie dei
appartenant au thread principal peut être affecté, même si elle estthread_local
. Ce programme permettra donc de sortie "42". Si vous le faites, alors vous devez prendre soin que*p
n'est pas accessible après le thread qu'il appartient à a quitté, sinon vous obtiendrez un bancales pointeur et un comportement indéterminé comme tout autre cas où la pointe-à l'objet est détruit.thread_local
les variables sont initialisées "avant la première utilisation", donc si ils ne sont jamais touchés par un thread donné alors qu'ils ne sont pas nécessairement toujours initialisé. Ceci afin de permettre aux compilateurs pour éviter de construire tous lesthread_local
variable dans le programme pour un thread qui est entièrement autonome et ne touchez pas l'un d'eux. par exemple,Dans ce programme il y a 2 fils: le thread principal et de la main-créé fil. Aucun thread appelle
f
, de sorte que lethread_local
objet n'est jamais utilisé. Il n'est donc pas spécifié si le compilateur va construire 0, 1 ou 2 cas demy_class
, et le résultat peut être "", "hellohellogoodbyegoodbye" ou "hellogoodbye".g()
appel au début dethreadFunc
, alors la sortie sera0304029
ou une autre permutation des paires02
,03
, et04
. Qui est, même si 9 est attribué ài
avant la création de threads, les fils se fraîchement construit copie dei
oùi=0
. Sii
est attribué, avecthread_local int i = random_integer()
, puis chaque thread obtient un nouveau nombre entier aléatoire.02
,03
,04
, il y a peut être d'autres séquences comme020043
Thread-local de stockage est dans tous les aspects comme statique (= global) de stockage, seulement que chaque thread a une copie de l'objet. L'objet de temps de la vie commence au début de fil (pour les variables globales) ou au début de l'initialisation (pour bloc locales statiques), et se termine lorsque le thread se termine (c'est à dire quand
join()
est appelé).Par conséquent, seules les variables qui pourraient également être déclaré
static
peut être déclaré commethread_local
, c'est à dire des variables globales (plus précisément: les variables "à portée espace de noms"), les membres de classe statiques, et le bloc des variables statiques (dans ce cas,static
est implicite).Comme un exemple, supposons que vous disposez d'un pool de threads et vous voulez savoir comment bien votre charge de travail est équilibrée:
Ce serait d'imprimer thread statistiques d'utilisation, par exemple, avec une mise en œuvre comme ceci: