Saltar al contenido

¿Cuál es la diferencia entre Lock y RLock?

Solución:

La principal diferencia es que un Lock solo se puede adquirir una vez. No se puede volver a adquirir hasta que se publique. (Después de su lanzamiento, cualquier hilo puede volver a adquirirlo).

Un RLock por otro lado, se pueden adquirir varias veces, por el mismo hilo. Debe liberarse el mismo número de veces para poder “desbloquearlo”.

Otra diferencia es que un adquirido Lock puede ser liberado por cualquier hilo, mientras que un adquirido RLock sólo puede ser liberado por el hilo que lo adquirió.


Aquí hay un ejemplo que demuestra por qué RLock es útil a veces. Suponga que tiene:

def f():
  g()
  h()

def g():
  h()
  do_something1()

def h():
  do_something2()

Digamos todos f, g, y h están público (es decir, puede ser llamado directamente por un llamador externo), y todos ellos requieren sincronización.

Usando un Lock, puedes hacer algo como:

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()

Básicamente, desde f no puedo llamar g después de adquirir el bloqueo, debe llamar a una versión “sin procesar” de g (es decir _g). Así que terminas con una versión “sincronizada” y una versión “sin procesar” de cada función.

Usando un RLock resuelve elegantemente el problema:

lock = RLock()

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

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

def h():
  with lock:
    do_something2()

Para ampliar la respuesta de shx2, la razón por qué quieres usar uno frente al otro podría ser lo siguiente:

Un habitual Lock (mutex) suele ser más rápido y seguro.

La razón para usar RLock es evitar un bloqueo muerto debido, por ejemplo, a la recursividad. Por ejemplo, pongamos un candado en la función factorial recursiva. (es cierto que algo artificial)

from threading import Lock

lock = Lock()

def factorial(n):
    assert n > 0
    if n == 1:
        return 1
    
    with lock:       
        out = n * factorial(n - 1)

    return out

Esta función provocará un bloqueo muerto debido a la llamada recursiva. Si usamos RLock en cambio, sin embargo, las llamadas recursivas pueden volver a ingresar al mismo bloqueo tantas veces como sea necesario. De ahí el nombre reentrante (o recursivo) cerrar con llave.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *