TL;DR

再入可能なロック(Reentrant lock)に対応した mutex。同じスレッドであれば、複数回ロックできる。

仕組み

ロックの状態を、所有権の有無ではなく、ロックカウント(ロックした回数)で表す。

例

Java の ReentrantLock のドキュメントによると、このロックは、最後にロックに成功してまだ解放していないスレッドが所有する。ほかのスレッドが所有していなければ lock はロックを取って返り、呼んだスレッドがすでに所有していれば、すぐに返る。所有しているかは isHeldByCurrentThread() で、ロックした回数は getHoldCount() で確かめられる。同じスレッドは最大 2147483647 回まで再帰的にロックできる。

lock を呼んだら、すぐ後に try を書き、finally で解放するのが推奨されている。

class X {
  private final ReentrantLock lock = new ReentrantLock();
 
  public void m() {
    lock.lock();
    try {
      // メソッドの本体
    } finally {
      lock.unlock();
    }
  }
}

注意点

Java や C++ には存在するが、Go の sync.Mutex は意図的に採用しておらず、再入できない(Non-reentrant lock)。

通常の mutex で十分な場面では、Recursive mutex を使うべきではない。

関連

出典