文档:https://en.cppreference.com/w/cpp/thread/recursive_mutex
好奇它的实现。
找 clang 的 <mutex>
源码:https://github.com/llvm/llvm-project/blob/main/libcxx/include/mutex#L213
发现 lock 调用了 __libcpp_recursive_mutex_lock(&_m),其中 m 是 __libcpp_recursive_mutex_t。
看 __threading_support:https://github.com/llvm/llvm-project/blob/58a0dcee8009d6504ce05874e644eb1df1276a11/libcxx/include/__threading_support#L205
typedef pthread_mutex_t __libcpp_recursive_mutex_t;
int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
{
return pthread_mutex_lock(__m);
}
int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
{
return pthread_mutex_trylock(__m);
}
平平无奇。
最后发现关键来自于构造函数,或者说 init:
inline _LIBCPP_ALWAYS_INLINE
int __libcpp_recursive_mutex_init(__libcpp_mutex_t* __m)
{
pthread_mutexattr_t attr;
int __ec = pthread_mutexattr_init(&attr);
if (__ec) return __ec;
__ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
if (__ec)
{
pthread_mutexattr_destroy(&attr);
return __ec;
}
__ec = pthread_mutex_init(__m, &attr);
if (__ec)
{
pthread_mutexattr_destroy(&attr);
return __ec;
}
__ec = pthread_mutexattr_destroy(&attr);
if (__ec)
{
pthread_mutex_destroy(__m);
return __ec;
}
return 0;
}
初始化锁会调用 pthread_mutexattr_settype,为锁添加 PTHREAD_MUTEX_RECURSIVE 属性。
查看 die.net,这个属性来自 pthread,可能的实现是多一个计数,同一个线程每次 lock 计数+1,每次 unlock 计数-1.
https://linux.die.net/man/3/pthread_mutexattr_settype
PTHREAD_MUTEX_RECURSIVE
A thread attempting to relock this mutex without first unlocking it shall succeed in locking the mutex. The relocking deadlock which can occur with mutexes of type PTHREAD_MUTEX_NORMAL cannot occur with this type of mutex. Multiple locks of this mutex shall require the same number of unlocks to release the mutex before another thread can acquire the mutex. A thread attempting to unlock a mutex which another thread has locked shall return with an error. A thread attempting to unlock an unlocked mutex shall return with an error.
注:可重入锁被认为比较危险,因为会掩盖死锁的真相,详见:http://www.zaval.org/resources/library/butenhof1.html