Ответ 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()