确保当前线程持有 C++11 互斥锁
Ensuring that current thread holds a lock on a C++11 mutex
有没有办法判断 C++11 中的当前线程是否持有互斥锁?特别是我想确保 class 中的某些函数仅在调用线程持有对象的锁(通过 std::lock_guard
、std::unique_lock
或类似的东西)时被调用, std::mutex
是一个成员变量。
为了避免在对象被广泛使用时重复锁定和解锁,锁定 mutex
的责任需要由调用者承担,不能在每个单独的函数中,如果当前线程当调用这些函数中的任何一个时,mutex
没有锁定,我想抛出异常。
看来我不能只使用 std::try_lock
然后根据需要进行解锁,因为如果当前线程已经持有锁,std::try_lock
的行为是未定义的。
只需在您的代码中使用 recursive mutex 和 lock/unlock,就像您在没有上层锁保证的情况下所做的那样。然后将 mutex
也提供给可以使用它(或不使用它)的调用代码。
最重要的是,如果上层没有锁定,您的代码仍然可以完美运行,尽管速度可能会降低。如果上层确实锁定,这只不过是检查它是否拥有锁和引用计数 increment/decrement,与您计划执行的开销类似。
C++ 标准库中(当前)没有定义任何接口,允许您检查互斥体是否被锁定以及您是否是所有者。
我建议这样做的方法是让只能在持有互斥量时调用的函数引用 std::unique_lock
或 std::lock_guard
。在 unique_lock
的情况下,您可能还想断言它实际上持有锁。
这将利用编译器来执行您的要求。
大概这些函数是您的 class 内部/私有的,并且您有面向用户的函数获取锁然后调用这些函数。如果是这样,有一个额外的参数不会污染面向 API.
的用户
大致如下:
// public
void A::public_function() {
std::lock_guard<std::mutex> l(m_mutex);
// ... do stuff
b(l);
// ... do more stuff
}
// private
void A::b(std::lock_guard const& l) {
// ... do stuff that requires holding the mutex
}
如果您需要使用 unique_lock
,只需在您的函数中断言 l.owns_lock()
为真(以防您想抛出异常)。
我对递归互斥锁的经验是,它们很容易让你不认真对待你的锁策略和所有权。而且他们以后可能会咬你。参见 this post。
有没有办法判断 C++11 中的当前线程是否持有互斥锁?特别是我想确保 class 中的某些函数仅在调用线程持有对象的锁(通过 std::lock_guard
、std::unique_lock
或类似的东西)时被调用, std::mutex
是一个成员变量。
为了避免在对象被广泛使用时重复锁定和解锁,锁定 mutex
的责任需要由调用者承担,不能在每个单独的函数中,如果当前线程当调用这些函数中的任何一个时,mutex
没有锁定,我想抛出异常。
看来我不能只使用 std::try_lock
然后根据需要进行解锁,因为如果当前线程已经持有锁,std::try_lock
的行为是未定义的。
只需在您的代码中使用 recursive mutex 和 lock/unlock,就像您在没有上层锁保证的情况下所做的那样。然后将 mutex
也提供给可以使用它(或不使用它)的调用代码。
最重要的是,如果上层没有锁定,您的代码仍然可以完美运行,尽管速度可能会降低。如果上层确实锁定,这只不过是检查它是否拥有锁和引用计数 increment/decrement,与您计划执行的开销类似。
C++ 标准库中(当前)没有定义任何接口,允许您检查互斥体是否被锁定以及您是否是所有者。
我建议这样做的方法是让只能在持有互斥量时调用的函数引用 std::unique_lock
或 std::lock_guard
。在 unique_lock
的情况下,您可能还想断言它实际上持有锁。
这将利用编译器来执行您的要求。
大概这些函数是您的 class 内部/私有的,并且您有面向用户的函数获取锁然后调用这些函数。如果是这样,有一个额外的参数不会污染面向 API.
的用户大致如下:
// public
void A::public_function() {
std::lock_guard<std::mutex> l(m_mutex);
// ... do stuff
b(l);
// ... do more stuff
}
// private
void A::b(std::lock_guard const& l) {
// ... do stuff that requires holding the mutex
}
如果您需要使用 unique_lock
,只需在您的函数中断言 l.owns_lock()
为真(以防您想抛出异常)。
我对递归互斥锁的经验是,它们很容易让你不认真对待你的锁策略和所有权。而且他们以后可能会咬你。参见 this post。