web-dev-qa-db-fra.com

Les variables d'instance Python sont-elles thread-safe?)

OK, vérifiez d'abord les codes suivants:

class DemoClass():

    def __init__(self):
        #### I really want to know if self.Counter is thread-safe. 
        self.Counter = 0

    def Increase(self):
        self.Counter = self.Counter + 1

    def Decrease(self):
        self.Counter = self.Counter - 1

    def DoThis(self):
        while True:
            Do something

            if A happens:
                self.Increase()
            else:
                self.Decrease()

            time.sleep(randomSecs)

    def DoThat(self):
        while True:
            Do other things

            if B happens:
                self.Increase()
            else:
                self.Decrease()

            time.sleep(randomSecs)

    def ThreadSafeOrNot(self):
        InterestingThreadA = threading.Thread(target = self.DoThis, args = ())
        InterestingThreadA.start()

        InterestingThreadB = threading.Thread(target = self.DoThat, args = ())
        InterestingThreadB.start()

Je fais face à la même situation que ci-dessus. Je veux vraiment savoir si c'est thread-safe pour self.Counter, Eh bien sinon, quelles options ai-je? Je ne peux penser qu'à threading.RLock() pour verrouiller cette ressource, une meilleure idée?

22
Shane

Vous pouvez utiliser des verrous, des verrouillages, des sémaphores, des conditions, des événements et des files d'attente.
Et cet article m'a beaucoup aidé .
Allez voir: Blog de Laurent Luce

33
aayoubi

Utilisation du champ d'instance self.Counter est thread-safe ou "atomic" . En le lisant ou en lui attribuant une valeur unique - même s'il a besoin de 4 octets en mémoire, vous n'obtiendrez jamais une valeur à moitié modifiée. Mais l'opération self.Counter = self.Counter + 1 n'est pas parce qu'il lit la valeur, puis l'écrit - un autre thread peut changer la valeur du champ après sa lecture et avant sa réécriture.

Vous devez donc protéger l'ensemble de l'opération avec une serrure.

Étant donné que le corps de la méthode est essentiellement toute l'opération, vous pouvez utiliser un décorateur pour ce faire. Voir cette réponse pour un exemple: https://stackoverflow.com/a/490090/34088

27
Aaron Digulla

Non, ce n'est pas sûr pour les threads - les deux threads modifient essentiellement la même variable simultanément. Et oui, la solution est l'un des mécanismes de verrouillage du module threading.

BTW, self.Counter est une variable d'instance, pas une variable de classe.

10
Eli Bendersky

self.Counter Est une variable d'instance, donc chaque thread a une copie.

Si vous déclarez la variable en dehors de __init__(), ce sera une variable de classe. Toutes les instances de la classe partageront cette instance.

3
Jack Mason