web-dev-qa-db-ja.com

LockとRLockの違いは何ですか

docs から:

threading.RLock()-新しいリエントラントロックオブジェクトを返すファクトリ関数。再入可能なロックは、それを取得したスレッドによって解放される必要があります。スレッドがリエントラントロックを取得すると、同じスレッドがブロックせずに再度ロックを取得できます。スレッドは、取得するたびに一度解放する必要があります。

なぜこれが必要なのか分かりませんか? RlockLockの違いは何ですか?

49
BufBills

主な違いは、Lockは1回しか取得できないことです。リリースされるまで、再度取得することはできません。 (リリース後、どのスレッドでも再取得できます)。

一方、RLockは、同じスレッドで複数回取得できます。 「ロック解除」するには、同じ回数だけリリースする必要があります。

別の違いは、取得したLockはどのスレッドでも解放できるのに対し、取得したRLockはそれを取得したスレッドのみが解放できることです。


以下は、RLockが時々役立つ理由を示す例です。あなたが持っていると仮定します:

def f():
  g()
  h()

def g():
  h()
  do_something1()

def h():
  do_something2()

fg、およびhのすべてがpublic(つまり、外部の呼び出し元から直接呼び出すことができる)であり、それらすべてが同期が必要です。

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