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 を使うべきではない。