web-dev-qa-db-fra.com

Quelle est la différence entre Lock et RLock

De la docs :

threading.RLock () - Fonction d'usine qui renvoie un nouvel objet de verrouillage réentrant. Un verrou rentrant doit être libéré par le fil qui l'a acquis. Une fois qu'un thread a acquis un verrou rentrant, le même thread peut l'acquérir à nouveau sans le bloquer; le thread doit le relâcher une fois pour chaque fois qu'il l'a acquis.

Je ne sais pas pourquoi en avons-nous besoin? quelle est la différence entre Rlock et Lock?

49
BufBills

La principale différence est qu'un Lock ne peut être acquis qu'une seule fois. Il ne peut pas être acquis à nouveau, jusqu'à ce qu'il soit libéré. (Après sa sortie, elle peut être ré-acquise par n'importe quel thread).

Un RLock d'autre part, peut être acquis plusieurs fois, par le même thread. Il doit être libéré le même nombre de fois pour être "déverrouillé".

Une autre différence est qu'un Lock acquis peut être publié par n'importe quel thread, tandis qu'un RLock acquis ne peut être publié que par le thread qui l'a acquis.


Voici un exemple démontrant pourquoi RLock est parfois utile. Supposons que vous ayez:

def f():
  g()
  h()

def g():
  h()
  do_something1()

def h():
  do_something2()

Disons que tous les f, g et h sont public (c'est-à-dire peuvent être appelés directement par un appelant externe), et tous nécessitent une synchronisation.

En utilisant un Lock, vous pouvez faire quelque chose comme:

lock = Lock()

def f():
  with lock:
    _g()
    _h()

def g():
  with lock:
    _g()

def _g():
  _h()
  do_something1()

def h():
  with lock:
    _h()

def _h():
  do_something2()

Fondamentalement, puisque f ne peut pas appeler g après avoir acquis le verrou, il doit appeler une version "brute" de g (c'est-à-dire _g). Vous vous retrouvez donc avec une version "synchronisée" et une version "brute" de chaque fonction.

L'utilisation d'un RLock résout élégamment le problème:

lock = RLock()

def f():
  with lock:
    g()
    h()

def g():
  with lock:
    h()
    do_something1()

def h():
  with lock:
    do_something2()
106
shx2