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

Из документов :

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

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

благодаря

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

    С другой стороны, 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()