В чем разница между Lock и RLock

С docs:

потоков.RLock() -- Заводская функция, возвращающая новый объект блокировки reentrant. Повторная блокировка должна быть освобождена потоком, который ее получил. Как только нить приобрела реентрантную блокировку, та же самая нить может приобрести ее снова без блокировки; нить должна освободить ее один раз за каждый раз, когда она ее приобрела.

Я не уверен, зачем нам это надо? в чем разница между Rlock и Lock?

1 ответов


главное отличие в том, что a Lock можно приобрести только один раз. Она не может быть приобретена снова, пока не будет освобождена. (После того, как он был выпущен, его можно повторно получить любым потоком).

An RLock С другой стороны, можно получить несколько раз, одним и тем же потоком. Он должен быть выпущен столько же раз, чтобы быть "разблокирован".

другое отличие заключается в том, что приобретенный Lock может быть выпущен любым потоком, в то время как приобретенный RLock может быть освобожден только нитью, которая его приобрела.


вот пример демонстрации почему RLock иногда полезно. Предположим, у вас есть:

def f():
  g()
  h()

def g():
  h()
  do_something1()

def h():
  do_something2()

скажем, все f, g и h are общественные (т. е. может вызываться напрямую внешним вызывающим), и все они требуют синхронизации.

С помощью Lock, вы можете сделать что-то вроде:

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

в основном, так как f не могу назвать g после приобретения блокировки необходимо вызвать "сырую" версию g (т. е. _g). Таким образом, вы получаете "синхронизированную" версию и "сырую" версию каждой функции.

С помощью RLock элегантно решает проблему:

lock = RLock()

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

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

def h():
  with lock:
    do_something2()