根据this,unique_lock
可以通过声明std::unique_lock<std::recursive_mutex>
来用于递归锁定,实际上编译得很好。
然而,从检查代码(gcc 4.8.2和4.9.0)看来,unique_lock
并不遵循_Mutex.lock
,而是实现了锁定方法本身:
void
lock()
{
if (!_M_device)
__throw_system_error(int(errc::operation_not_permitted));
else if (_M_owns)
__throw_system_error(int(errc::resource_deadlock_would_occur));
else
{
_M_device->lock();
_M_owns = true;
}
显然,这可以防止互斥锁的递归锁定,并且实际上尝试以递归方式锁定抛出resource_deadlock_would_occur
异常。
我在这里遗漏了什么,这是一个错误,还是unique_lock的文档错了?
TIA !!!
答案 0 :(得分:19)
常见的错误是将mutex
与lock
混淆。 mutex
是一个可以在线程之间共享的对象(否则它将是无用的)。然而,锁本身不是一个线程安全的对象。它不应该在线程之间共享。它通常是堆栈上的本地对象。例如:
void foo()
{
std::unique_lock<std::mutex> lk(mut); // mut comes from some other scope
// mut locked here
// ...
} // mut unlocked here
在上面的示例中,如果以递归方式调用foo()
,则会有未定义的行为,因为您将递归锁定mut
。在每次递归时,您会得到一个新的unique_lock
。所以unique_lock
不知道递归。如果您确实需要递归调用foo()
,则需要使用递归互斥锁,例如:
void foo()
{
std::unique_lock<std::recursive_mutex> lk(mut); // mut comes from some other scope
// mut locked here
// ...
} // mut unlocked here
所以:是的,您可以使用std::unique_lock<std::recursive_mutex>
,是的,您的实施是正确的。