一般来说,一个简单的互斥锁是一个32位的键,其中0-30位包含所有者的线程 ID,31位标记表示互斥锁是否有等待者。它有一个 lock 方法,这是一个 CAS 原子竞赛,在发生故障时用一个 syscall 声明互斥锁。细节不重要。它看起来像这样:
class mutex {
public:
void lock();
void unlock();
protected:
uint32_t key{}; //bits 0-30: thread_handle, bit 31: hasWaiters_flag
};
递归 _ 互斥对象通常实现为:
class recursive_mutex : public mutex {
public:
void lock() {
uint32_t handle = current_thread_native_handle(); //obtained from TLS memory in most OS
if ((key & 0x7FFFFFFF) == handle) { // Impossible to return true unless you own the mutex.
uses++; // we own the mutex, just increase uses.
} else {
mutex::lock(); // we don't own the mutex, try to obtain it.
uses = 1;
}
}
void unlock() {
// asserts for debug, we should own the mutex and uses > 0
--uses;
if (uses == 0) {
mutex::unlock();
}
}
private:
uint32_t uses{}; // no need to be atomic, can only be modified in exclusion and only interesting read is on exclusion.
};
如您所见,它完全是一个用户空间构造。(base mutex 不是这样的,如果它在原子比较和锁定交换中没有获得密钥,它可能会进入系统调用,如果 has _ waitersFlag 打开,它会在解锁时进行系统调用)。