La differenza principale è che un Lock
può essere acquisito solo una volta. Non può essere acquisito di nuovo fino a quando non viene rilasciato. (Dopo che è stato rilasciato, può essere riacquisito da qualsiasi thread).
Un RLock
d'altra parte, può essere acquisito più volte, dallo stesso thread. Deve essere rilasciato lo stesso numero di volte per essere "sbloccato".
Un'altra differenza è che uno Lock
acquisito può essere rilasciato da qualsiasi thread, mentre un RLock
acquisito può essere rilasciato solo dal thread che lo ha acquisito.
Ecco un esempio dimostrativo del motivo per cui lo RLock
è utile a volte. Supponiamo di avere:
def f():
g()
h()
def g():
h()
do_something1()
def h():
do_something2()
Diciamo tutti f
, g
, e h
sono pubblico (cioè può essere chiamato direttamente da un chiamante esterno), e tutte richiedono sincronizzazione.
Utilizzando un Lock
, si può fare qualcosa di simile:
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()
In sostanza, dal momento che f
non può chiamare g
dopo aver acquisito la serratura, ha bisogno di chiamare un versione "grezza" di g
(vale a dire _g
). Quindi si finisce con una versione "sincronizzata" e una versione "raw" di ogni funzione.
Utilizzando un RLock
risolve elegantemente il problema:
lock = RLock()
def f():
with lock:
g()
h()
def g():
with lock:
h()
do_something1()
def h():
with lock:
do_something2()