129 votes

Qu'est-ce que le "stockage local des threads" en Python et pourquoi en ai-je besoin?

En Python, plus précisément, comment les variables seront partagées entre les threads?

Bien que je l'ai utilisé, threading.Thread avant je n'ai jamais vraiment compris ou vu des exemples de la manière dont les variables suis partagé. Sont-ils partagés entre le sujet principal et les enfants ou seulement parmi les enfants? Quand aurais-je besoin pour utiliser le thread local de stockage pour éviter ce partage?

J'ai vu beaucoup de mises en garde sur la synchronisation des accès aux données partagées entre les threads à l'aide de verrous, mais je n'ai pas encore vu un très bon exemple de ce problème.

Merci à l'avance!

112voto

Thomas Wouters Points 38811

En Python, tout est partagé, à l'exception de la fonction de variables locales (parce que chaque appel de fonction obtient son propre ensemble de la population locale, et les fils sont toujours séparés des appels de fonction.) Et même alors, seulement les variables elles-mêmes (les noms qui se réfèrent à des objets) sont locales à la fonction; les objets eux-mêmes sont toujours globales, et tout ce qui peut s'y référer. L' Thread objet particulier d'un thread n'est pas un objet spécial à cet égard. Si vous stockez l' Thread objet quelque part tous les threads peuvent accéder (comme une variable globale), alors tous les threads peuvent accéder qu'un Thread objet. Si vous voulez atomiquement modifier quelque chose que vous n'avez pas il suffit de créer dans ce même fil, et ne pas stocker n'importe où à un autre thread peut obtenir, vous devez le protéger par un verrou. Et tous les threads doivent partager la même serrure, ou il ne serait pas très efficace.

Si vous voulez réelle de stockage local des threads, c'est là qu' threading.local . Les attributs de l' threading.local ne sont pas partagées entre les threads; chaque thread ne voit que les attributs il a lui-même placé là. Si vous êtes curieux au sujet de sa mise en œuvre, la source est en _threading_local.py dans la bibliothèque standard.

93voto

ahatchkins Points 231

Considérons le code suivant:

#/usr/bin/env python

from time import sleep
from random import random
from threading import Thread, local

data = local()

def bar():
    print "I'm called from", data.v

def foo():
    bar()

class T(Thread):
    def run(self):
        sleep(random())
        data.v = self.getName()   # Thread-1 and Thread-2 accordingly
        sleep(1)
        foo()
 >> T().start(); T().start()
Je suis appelé à partir du Fil-2
Je suis appelé à partir de Fil-1 

Ici le filetage.local() est utilisé comme une façon rapide et sale de transmettre certaines données à partir de run() de la barre (de), sans changer l'interface de foo().

Notez que l'utilisation de variables globales ne suffit pas:

#/usr/bin/env python

from time import sleep
from random import random
from threading import Thread

def bar():
    global v
    print "I'm called from", v

def foo():
    bar()

class T(Thread):
    def run(self):
        global v
        sleep(random())
        v = self.getName()   # Thread-1 and Thread-2 accordingly
        sleep(1)
        foo()
 >> T().start(); T().start()
Je suis appelé à partir du Fil-2
Je suis appelé à partir du Fil-2 

En attendant, si vous pouvez vous permettre de passer ces données sous la forme d'un argument de foo() - il serait plus élégant et bien conçu de manière à:

from threading import Thread

def bar(v):
    print "I'm called from", v

def foo(v):
    bar(v)

class T(Thread):
    def run(self):
        foo(self.getName())

Mais ce n'est pas toujours possible lors de l'utilisation de tiers ou mal conçus code.

27voto

Aaron Maenpaa Points 39173

Vous pouvez créer un stockage local de thread en utilisant threading.local() .

 >>> tls = threading.local()
>>> tls.x = 4 
>>> tls.x
4
 

Les données stockées dans les fichiers seront uniques à chaque thread, ce qui permettra d'éviter tout partage involontaire.

3voto

Nick Johnson Points 79909

Tout comme dans toute autre langue, tous les threads en Python a accès aux mêmes variables. Il n'y a pas de distinction entre le "fil conducteur" et threads enfants.

Une différence avec Python, c'est que le blocage de l'interpreteur Global signifie qu'un seul thread peut exécuter du code Python à la fois. Ce n'est pas beaucoup d'aide quand il s'agit de la synchronisation de l'accès, cependant, comme tous l'habitude de préemption s'applique, et vous devez utiliser des primitives de thread, tout comme dans d'autres langues. Cela signifie que vous devez reconsidérer si vous avez été en utilisant des fils de la performance, cependant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X