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?
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
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
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.
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.