Подтвердить что ты не робот

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

Из docs:

threading.RLock() - A factory, которая возвращает новый объект блокировки ретентата. Блокировка реентера должна быть освобождена потоком, который его приобрел. После того, как поток приобрел блокировку реентера, тот же поток может получить его снова без блокировки; поток должен освобождать его один раз за каждый раз, когда он его приобрел.

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

спасибо

4b9b3361

Ответ 1

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

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

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


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

def f():
  g()
  h()

def g():
  h()
  do_something1()

def h():
  do_something2()

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

Используя 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()